如何在功能上处理来自外部系统的状态?

2024-04-09

我最近进入了函数式编程,并且学习了几种以引用透明的方式处理某些副作用的方法:

  • 国家单子 http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1对于可变状态,例如更新变量
  • IO 单子 http://james-iry.blogspot.com/2007/11/monads-are-elephants-part-4.html用于 I/O,例如从控制台读取/写入
  • FRP http://flapjax-lang.org用于图形和输入设备事件等交互

但现在大多数“现实世界”的应用程序都与外部系统(如 Web 服务、数据库等)进行交互,这些系统可以由多个用户同时修改,它们具有状态、长时间运行的操作等。所以情况并不那么简单与上述类别一样:向系统询问实体的状态或尝试控制它的结果取决于其状态。此外,交互性也是一个要求:有一些用户可以任意点击的GUI,也许我们还必须自动对来自系统的变化做出反应。

通过最大化纯函数的优势来设计和实现此类应用程序的模式是什么?或者上面的一些方法可以以我没有想到的方式应用于这个问题吗?该语言(例如 Java 或 Scala)并不强制要求 100% 的纯度,因此我对由实践经验支持的实用解决方案感兴趣。


我还没有做过很多这样的事情,但实际上已经以实际的方式完成了,所以希望其他人能够做得更多。不过,我已经用 Scala 编写了一个 Android 应用程序,它满足了您的一些要求; UI 是交互式的,“状态”全部存储在 SQLite 数据库中。数据库和 UI 都需要与 Android 框架交互,而 Android 框架很大程度上是面向 Java 的,因此不太适合 Scala 或函数式编程。

我所做的是采用类似于 MVC 的设计,其中模型部分作为一组仅支持纯操作的 ADT 来实现。这样做的另一个优点是模型代码完全独立于 Android 框架,因此可以在模拟器之外以我喜欢的任何方式进行测试。

这给我留下了控制器(视图是一个非常薄的层,主要只是配置,按照 Android 的工作方式),加上“从数据库加载模型”和“将模型保存到数据库”的附加操作。作为 Scala,我只是用不纯的代码实现了这些部分,这些代码调用纯模型代码来执行实际的数据操作。在 Haskell 中,这些部分可能完全位于 IO monad 中[1]。

总而言之,这使我能够以纯功能的方式思考我的问题领域,而不必在与外部系统交互时“违背常规”。数据库层成为数据库模式和我用于数据模型的 ADT 之间的映射问题;处理这些操作可能失败的事实是控制器(启动数据库操作)的责任,并且不会影响模型。控制器操作在概念上变得非常简单,例如“当按下此按钮时,将当前状态设置为在当前状态上调用函数的结果,然后更新显示表”。最终,这种不纯的“粘合”代码比实际的模型代码要多得多,但我仍然认为以这种方式编写程序是一个胜利,因为我的应用程序的核心是操纵复杂的结构化数据,所以做到这一点是最棘手的。其余的大部分是编写起来很乏味,而不是设计起来很困难。

当您的程序中有大量计算(不一定是大量计算)时,这会起作用。data,只是你实际上在上面计算了东西)。如果该程序几乎完全将不同的外部系统粘合在一起,那么您不一定能获得那么多收益。


[1] 请记住,IO monad 不仅仅用于从控制台读取/写入。其结果受程序外部状态影响的建模操作正是 IO monadfor;一般来说,如果 IO monad 不一直与外部系统交互(或者最好即使是这样),Haskeller 会尽量避免在几乎整个程序中使用 IO monad。您可以对数据进行纯计算以响应来自“外部”的事件,甚至可以进行纯计算of响应外部事件需要执行的 IO 操作(如果很复杂)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在功能上处理来自外部系统的状态? 的相关文章

  • D 中的特征可以用于类型类吗?

    我是 D 新手 我正在寻找一种使用类似 Haskell 的类型类进行编程的好方法 例如D 中的函子 幺半群等 Tango 或 Phobos 中是否实现了类似的功能 我听说过可以对某些属性进行编译时类型检查的特征 它们可以用于类型类吗 我尝试
  • 是否可以有效地计算 lambda 演算项?

    我最近用 lambda 演算编写了很多程序 我希望能够实时运行其中一些程序 然而 尽管趋势函数范式基于 lambda 演算和 B 约简规则 但我找不到一个不是玩具 不以效率为目的的评估器 函数式语言应该很快 但我所知道的那些语言实际上并不提
  • 使用参与者模型进行基于时间的模拟

    我们有一个单线程应用程序 可以模拟数十万个对象随着时间的推移与共享内存模型的交互 显然 它无法在多 CPU 硬件上进行扩展 在阅读了一些有关基于代理的建模和函数式编程 参与者模型的内容后 我正在考虑使用消息传递范例进行重写 这个想法非常简单
  • 如何根据列表中的先前值过滤Haskell中的列表元素?

    我正在努力在 Haskell 中创建一个函数 该函数根据列表中前一个元素的条件过滤列表的数字 Example 前一个数字是 2 的倍数 myFunction 1 2 5 6 3 expected output 5 3 我知道如何申请filt
  • 为什么 x = x +1 在 Elixir 中有效?

    我读到的有关 Elixir 的所有内容都表明 赋值应该被视为模式匹配 如果是这样 为什么 x x 1 在 Elixir 中有效 不存在 x x 1 的 x 值 我读到的有关 Elixir 的所有内容都表明 赋值应该被视为模式匹配 在长生不老
  • 与可变结构相比,不可变结构有哪些优点?

    我已经知道不变性相对于可变性的好处在于能够推理代码并引入更少的错误 尤其是在多线程代码中 不过 在创建结构时 我看不出创建一个完全不可变的结构比创建一个可变的结构有任何好处 让我们以保存一些分数的结构为例 struct ScoreKeepe
  • 在自己的定义中使用变量?

    无限流 val ones Stream Int Stream cons 1 ones 一个值怎么可能在它自己的声明中使用呢 看起来这应该会产生编译器错误 但它确实有效 它并不总是递归定义 这实际上有效并产生 1 val a Int a 1
  • python函数返回函数[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • OCaml 作为 C 库,hello world 示例

    我希望通过 C 调用 OCaml 代码 方法是将 OCaml 编译为包含 C 接口的静态或共享库 这一页 https caml inria fr pub docs manual ocaml intfc html似乎解释了如何为 OCaml
  • 什么样的函数被认为是“可组合的”?

    维基百科文章函数组合 计算机科学 https en wikipedia org wiki Function composition computer science says 就像数学中通常的函数组合一样 每个函数的结果作为下一个函数的参数
  • Vim 脚本中的“reduce”函数

    Vim 脚本有一些非常基本的函数式编程工具 It has map and filter 但据我所知它缺乏reduce 功能 Reduce https en wikipedia org wiki Fold 28higher order fun
  • 是否可以只迭代一个流一次并执行 2 个或更多操作?

    给定代码 List
  • std::bind 重载解析

    下面的代码工作正常 include
  • 数量重新分配逻辑 - 具有外部数据集的 MapGroups

    我正在研究一种复杂的逻辑 需要将数量从一个数据集重新分配到另一个数据集 在例子中我们有Owner and Invoice 我们需要从数量中减去Invoice准确地Owner匹配 在给定汽车的给定邮政编码处 减去的数量需要重新分配回同一辆车出
  • 你能在 scala 中使用 varargs 柯里化一个函数吗?

    我正在考虑如何用可变参数柯里化一种方法 然后我意识到我什至不知道如何去做 理想情况下 它应该让您可以随时开始使用它 然后以可迭代结束 def concat strs String strs mkString val curriedConca
  • 构造微积分中的“Refl”东西?

    在语言中 例如Agda Idris or Haskell对于类型扩展 有一个 键入类似于以下内容的内容 data a b where Refl a a a b意思是a and b是相同的 这样的类型可以定义在结构演算 https en wi
  • 通过消除嵌套的 for 循环来改进此代码

    R 包corrplot除其他内容外 还包含这个漂亮的功能 cor mtest lt function mat conf level 0 95 mat lt as matrix mat n lt ncol mat p mat lt lowCI
  • 返回带有参数的函数的函数

    创建一个应返回包含原始函数参数的函数时 我应该如何处理 例如考虑这个函数 a lt function value function x x value 我希望它返回我在结果函数的参数中指定的值 如下所示 b lt a 3 gt b gt f
  • 哪种编程语言或库可以处理无限级数?

    哪种编程语言或库能够处理无限级数 例如几何级数或调和级数 它可能必须有一些众所周知的系列的数据库 并在收敛的情况下自动给出适当的值 并且可能在发散的情况下生成异常 例如 在 Python 中 它可能如下所示 sum 0 sign 1 0 f
  • 如何使用 rxpy/rxjs 延迟事件发射?

    我有两个事件流 一个来自电感环路 另一个来自网络摄像机 汽车将驶过环路 然后撞上相机 如果事件彼此相差在 N 毫秒内 汽车总是会首先进入循环 我想将它们组合起来 但我也希望每个流中不匹配的事件 硬件可能会失败 全部合并到单个流中 像这样的事

随机推荐