什么是(功能性)反应式编程?
我已阅读维基百科有关反应式编程的文章。 我也读过关于功能性反应式编程的小文章。 描述非常抽象。
我的背景是命令/面向对象的语言,因此与此范例相关的解释将值得赞赏。
如果你想获得FRP的感觉,你可以从1998年的旧版Fran教程开始,它有动画插图。 对于论文,请先从Functional Reactive Animation开始,然后跟进我主页上的出版物链接链接以及Haskell wiki上的FRP链接。
就我个人而言,在讨论FRP如何实施之前,我喜欢思考FRP的含义。 (没有规范的代码是一个没有问题的答案,因此“甚至没有错”)。因此,我没有用表达/实现术语描述FRP,因为Thomas K在另一个答案(图形,节点,边缘,解雇,执行,等等)。 有许多可能的实现方式,但没有实现说明FRP是什么。
我对劳伦斯G的简单描述产生了共鸣,即玻璃钢是关于“随着时间的推移而代表价值的数据类型”。 传统的命令式编程仅通过状态和突变间接地捕获这些动态值。 完整的历史(过去,现在,未来)没有一流的代表性。 此外,由于命令范式在时间上是离散的,因此只能(间接)捕获离散演变的值。 相比之下,FRP直接捕捉这些不断变化的价值观,并且不断发展价值。
FRP也是不寻常的,因为它同时没有与理论和实用老鼠窝发生冲突,而这种老鼠巢困扰着势在必行的并发。 在语义上,FRP的并发性是细化的,确定的和连续的。 (我说的是意义,而不是实现,实现可能涉及或不涉及并发或并行)。语义确定性对于推理非常重要,无论是严格的还是非正式的。 虽然并发性增加了命令式编程的巨大复杂性(由于非确定性交错),但它在FRP中毫不费力。
那么,什么是玻璃钢? 你可以自己发明它。 从这些想法开始:
动态/不断变化的值(即“随着时间推移”的值)本身就是第一类值。 你可以定义它们并合并它们,将它们传入和传出函数。 我称这些为“行为”。
行为是由几个原语构成的,如恒定(静态)行为和时间(如时钟),然后是顺序和并行组合。 n行为通过应用n元函数(静态值),“逐点”(即,随着时间的推移连续)而被组合。
为了解释离散现象,有另一种类型(家庭)的“事件”,每个事件都有一个事件流(有限或无限)。 每个事件都有相关的时间和价值。
为了提出可以构建所有行为和事件的构图词汇,请参考一些例子。 保持解构成更加一般/简单的作品。
为了让你知道自己在坚实的基础上,使用指称语义技术给整个模型一个构图基础,这只意味着(a)每种类型都有相应的简单和精确的数学类型的“含义”,而b)每个原语和操作符都具有简单和精确的含义,作为成分的含义的函数。 永远不要将执行考虑因素混合到您的探索过程中。 (a)带类型态射的指称设计,(b)推挽功能反应式编程(忽略实现位),以及(c)指示语义Haskell wikibooks页面。 请注意,指称语义由两个创始人Christopher Strachey和Dana Scott两部分组成:更简单和更实用的Strachey部分以及更难和更少用于Scott软件设计的部分。
如果你坚持这些原则,我希望你会在玻璃钢的精神上得到或多或少的好处。
我在哪里得到这些原则? 在软件设计中,我总是问同样的问题:“这是什么意思?”。 指称语义为我提供了这个问题的精确框架,并且符合我的美学原理(与操作语义或公理语义不同,这两者都使我不满意)。 所以我问自己什么是行为? 我很快就意识到,命令式计算的时间离散性是对特定机器类型的适应,而不是对行为本身的自然描述。 我能想到的最简单的行为的精确描述仅仅是“(连续)时间的函数”,所以这就是我的模型。 令人高兴的是,这个模型轻松和优雅地处理连续的,确定性的并发。
正确高效地实施这个模型是一个相当大的挑战,但那是另一回事。
在纯函数式编程中,没有副作用。 对于许多类型的软件(例如,有用户交互的任何事物),在某种程度上,副作用是必需的。
在保持功能风格的同时获得类似副作用的行为的一种方法是使用功能性反应式编程。 这是功能编程和反应式编程的结合。 (你链接到的维基百科文章是关于后者。)
反应式编程背后的基本思想是,某些数据类型代表“随时间变化”的值。 涉及这些转换时间值的计算本身的值会随着时间而改变。
例如,您可以将鼠标坐标表示为一对整数随时间值。 假设我们有类似的东西(这是伪代码):
x = <mouse-x>;
y = <mouse-y>;
在任何时候,x和y都会有鼠标的坐标。 与非响应式编程不同,我们只需要进行一次赋值,并且x和y变量将自动保持“最新”。 这就是为什么反应式编程和函数式编程很好地结合在一起的原因:反应式编程消除了变异变异的需求,同时让您可以利用变异变异完成许多变异。
如果我们根据这个做一些计算,那么结果值也会随着时间而变化。 例如:
minX = x - 16;
minY = y - 16;
maxX = x + 16;
maxY = y + 16;
在这个例子中, minX
总是比鼠标指针的x坐标小16。 使用响应感知库,你可以这样说:
rectangle(minX, minY, maxX, maxY)
并且鼠标指针周围将绘制一个32x32的框,并在其移动的任何位置进行跟踪。
这是关于功能性反应式编程的一篇不错的论文。
想象一下你的程序是一个电子表格,而你所有的变量都是单元格,一个简单的方法就是直接了解它是什么。 如果电子表格中的任何单元格更改,则引用该单元格的任何单元格也会更改。 这与FRP一样。 现在想象一些细胞自己改变(或者更确切地说,是从外部世界获取的):在GUI情况下,鼠标的位置就是一个很好的例子。
这肯定会错过很多。 当你真正使用FRP系统时,这个隐喻很快就会崩溃。 首先,通常也会尝试模拟离散事件(例如,鼠标被点击)。 我只是在这里给你一个想法是什么。
链接地址: http://www.djcxy.com/p/1295.html上一篇: What is (functional) reactive programming?
下一篇: What is a monad?