函数式响应式编程

函数式响应式编程(FRP) 是一种编程范式,它采用函数式编程的基础部件(如mapreducefilter等),进行响应式编程异步数据流程编程)。FRP被用于GUI机器人和音乐方面的编程,旨在通过显式的建模时间来简化这些问题。

FRP的形式

函数式响应编程,自从1997年由Conal Elliott和保罗·胡达客在ICFP 97论文《函数式响应式动画》中提出以来[1],产生了多种形式。其多样性的一条轴线,是离散与连续语义对比。另一条轴线,是怎样让FRP系统可以动态地更改。[2]

连续

FRP的最早形式采用了连续的语义,旨在抽象出对程序的意义无关紧要的操作细节。[1]这种形式的关键属性为:

  • 建模在连续时间内变化的值,叫做“行为”,后来称为“信号”。
  • 建模“事件”,它发生在离散的时间点上。
  • 系统可在响应事件时被改变,通用采用术语“切换”。
  • 从响应模型中分离出求值细节,如采样率。

这种FRP语义模型在无副作用的语言中通常采用随时间变化的连续函数。[3]

离散

如事件驱动FRP和Elm在0.17版本之前的那种形式,它们要求更新过程是离散的,且由事件驱动。[4]这些形式在FRP的实践中被加以推崇,它们专注于拥有简单API的语义,比如在机器人或Web浏览器中可以被高效地实现。[5]

在这些形式下,行为和事件的概念通常会被合并成信号,它总是拥有当前值,但会被离散地改变。[6]

交互式FRP

Conal Elliott在2008年已经指出,从输入到输出,这种普通的FRP模型,不太适合交互式程序。[7]在从输入映射到输出的过程中缺乏“运行”程序的能力,可能意味着必须使用以下解决方案之一:

  • 创建表示行动的一个数据结构,它表现为输出。行动必须被一个外部的解释器或环境来运行。它继承了最初Haskell的流式I/O的全部难点。[8]
  • 使用箭头化的FRP,和有能力实行行动的嵌入箭头。行动也必须有身份标识,比如说使得它们可以做维护各自的可变存储。采取这种办法的是Fudgets库[9],和更一般性的单子流函数[10]
  • 最新颖的方法就是允许行动现在运行(于IO单子中),但将它们结果的接收推迟到以后。[11]它利用了事件和IO单子之间的交互,并兼容于更加面向表达式的FRP:
planNow :: Event (IO a) -> IO (Event a)

实现问题

存在两种类型的FRP系统,基于推送的和基于拉取的。基于推送的系统接收事件,并将它们推过一个信号网络来达成结果。基于拉取的系统会等待对结果的需求,并逆向通过该网络检索所需求的值。

某些FRP系统例如Yampa使用采样,这里将采样推过一个信号网络。这种方法有个缺点:网络在一个计算步骤持续期间必须等待,然后才能发现输入上的变更。采样就是个基于推送的FRP示例。

Hackage上的Reactive和Etage库介入了一种叫做“推送-拉取FRP”的方式。按照这种方式,只在需求纯粹定义的流(如随时间推移的固定事件的列表)上的下一个事件时,才会构造该事件。这些纯粹定义的流的行为类似于Haskell中的惰性列表。此为基于拉取的部分。基于推送的部分会在系统外部的事件被带入系统时使用到。外部的事件会被推送给消费者,这样它们就可以在它发布的瞬间找到该事件。

实现

  • Yampa[12],是一个箭头化、高效的、纯Haskell实现,支持SDL、SDL2、OpenGL和HTML DOM。
  • reflex[13],是一个高效的,用Haskell实现的推送/拉取式FRP,主要宿主是浏览器/DOM、SDL和Gloss。
  • reactive-banana[14],是一个用Haskell实现的目标不可知的推送式FRP。
  • netwire[15]和varying[16],是箭头化的,用Haskell实现的拉取式FRP。
  • Flapjax,是一个用JavaScript实现的行为/事件式FRP。
  • React[17],是用于函数式响应编程的一个OCaml模块。
  • Sodium[18],是独立于UI框架的推送式FRP实现,支持多种编程语言比如Java、TypeScript和C#。
  • ReactiveX,由它的JavaScript实现rxjs[19]而流行,是实现函数式响应式编程的综合性跨平台范型,将数据当作可观测者的流来处理。
  • Dunai[20],是支持类和箭头化FPR的,使用单子流函数的一个Haskell的快速实现。

另请参阅

  • Elm编程语言,曾经支持FRP[21],但是现在以不同的模式替代了它[22]
  • Ur编程语言,浏览器客户端包括了函数式响应式编程设施。
  • 增量计算
  • 串流处理

参考来源

  1. Elliott, Conal; Hudak, Paul, , , 1997 [2018-04-13], (原始内容存档于2020-11-11).
  2. Nilsson, Henrik; Courtney, Antony; Peterson, John, (PDF), (PDF) (2), Feb 2011 [2002] [2018-04-13], (原始内容 (PDF)存档于2017-10-10).
  3. Courtney, Antony; Elliott, Conal, , , Yale, Feb 2011 [2001] [2018-04-13], (原始内容存档于2022-04-13).
  4. Taha, Walid; Wan, Zhanyong; Hudak, Paul, , , Yale, 2002 [2021-03-02], (原始内容存档于2021-02-10).
  5. Czaplicki, Evan; Chong, Stephen, , , Harvard, 2013 [2018-04-13], (原始内容存档于2018-11-09).
  6. Wan, Zhanyong; Taha, Walid; Hudak, Paul, , (PDF) (1), Feb 2011.
  7. . [2018-04-13]. (原始内容存档于2015-07-24).
  8. (PDF). [2018-04-13]. (原始内容存档 (PDF)于2016-05-28).
  9. . [2018-04-13]. (原始内容存档于2020-01-24).
  10. Perez, Ivan; Barenz, Manuel; Nilsson, Henrik, , (PDF), July 2016 [2021-03-02], (原始内容存档 (PDF)于2017-05-18).
  11. Atze van der Ploeg; Koen Claessen. . [2021-03-04]. (原始内容存档于2020-04-25).
  12. . [2021-03-02]. (原始内容存档于2021-03-01).
  13. . [2018-04-13]. (原始内容存档于2020-11-11).
  14. . [2018-04-13]. (原始内容存档于2020-11-11).
  15. . [2018-04-13]. (原始内容存档于2020-10-20).
  16. . [2018-04-13]. (原始内容存档于2020-11-12).
  17. . [2021-03-02]. (原始内容存档于2020-12-24).
  18. . [2021-03-02]. (原始内容存档于2020-12-24).
  19. . [2021-03-02]. (原始内容存档于2021-05-17).
  20. . [2021-03-02]. (原始内容存档于2021-05-24).
  21. Czaplicki, Evan, (PDF) (thesis), Harvard, Apr 2012 [2021-03-02], (原始内容存档 (PDF)于2021-04-16).
  22. Czaplicki, Evan. . elm. [14 July 2018]. (原始内容存档于2019-05-31).

外部链接

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.