什么是(功能性)反应式编程? [英] What is (functional) reactive programming?

查看:135
本文介绍了什么是(功能性)反应式编程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读关于响应式编程的维基百科文章。我还阅读了关于功能性响应式编程的小文章。这些描述非常抽象。


  1. 功能性反应式编程(FRP)在实践中意味着什么?

  2. 反应式编程(与非反应式编程相反)包含什么?

我的背景是命令式的/面向对象语言,所以我们将赞赏与这种范式相关的解释。 $ b

解决方案

如果你想感受FRP,你可以从旧的弗兰教程从1998年,它具有动画插图。有关论文,请从 功能性动画动画 开始,然后跟进我的主页上的出版物链接以及 FRP 链接.org / haskellwiki / Haskellrel =noreferrer> Haskell wiki 。



我个人喜欢考虑FRP 然后再讨论如何实施。
(没有规范的代码是一个没有问题的答案,因此甚至没有错)
所以我没有用描述/实现术语来描述FRP,正如Thomas K在另一个答案中所做的那样(图表,节点,边缘,射击,执行等)。
有许多可能的实现风格,但没有实现说明FRP 是什么。



我对Laurence G的简单描述产生共鸣FRP是关于随着时间的推移代表价值的数据类型。
传统的命令式编程仅通过状态和突变间接捕获这些动态值。
完整的历史记录(过去,现在,将来)没有一流的表现形式。
此外,只有离散演变值可以(间接)捕获,因为命令范式是暂时离散的。
相比之下,FRP直接捕获这些不断变化的值,并且不会有任何问题持续发展。



玻璃钢也是不寻常的,因为它不会与理论和实践相抵触。困扰命令式并发的务实鼠窝。
语义上来说,FRP的并发性是细粒度的,em确定性的,em是连续的
(我说的是意义,而不是实现,实现可能涉及或不涉及并发或并行)。
语义确定性对于推理非常重要,无论是严格还是非正式的。
虽然并发性增加了命令式编程的复杂性(由于非确定性交错),但它在FRP中毫不费力。所以,什么是FRP?
你可以自己发明它。
以这些想法开始:


  • 动态/演变值(即随时间变化的值)价值本身。你可以定义它们并合并它们,并将它们传递给&超出功能。我称这些为行为。

  • 行为是由几个基元组成的,如常量(静态)行为和时间(如时钟),然后用顺序和平行组合。 n 行为通过应用n元函数(基于静态值),逐点(即,随着时间的推移而连续)来组合。


    为了提出构成词汇,其中可以构建所有行为和事件,请参阅一些示例。继续解构为更普遍/简单的作品。 为了让你知道自己在坚实的基础上,给整个模型一个构图基础,使用技术的指称语义,这只是意味着(a)每种类型都有相应的简单&精确的数学类型的含义,和(b)每个基元和算子具有简单的&精确含义作为成分含义的函数。
    永远不会将实施考虑事项混合到您的探索过程中。如果这个描述对你来说是无稽之谈,可以参考(a) 指称类型态射的指称设计 a>
    ,(b) 推拉功能反应式编程 (忽略实现位),和(c) 指称语义 em> Haskell wikibooks页面。请注意指称语义由两个创始人Christopher Strachey和Dana Scott两部分组成:更简单&更有用的Strachey部分和更难和不太有用的(用于软件设计)Scott部分。




如果你坚持这些原则,我希望你能以FRP的精神获得更多或更少的东西。



我从哪里得到这些原则?在软件设计中,我总是问同样的问题:这是什么意思?。
指示语义为我提供了一个精确的框架,适合我的美学(与操作语义或公理语义不同,这两者都让我不满意)。
所以我问自己什么是行为?
我很快意识到,命令式计算的时间离散性质是适应机器的特定风格,而不是行为本身的自然描述。
我能想到的最简单的行为的精确描述仅仅是(连续)时间的函数,所以这就是我的模型。
令人高兴的是,这个模型轻松且优雅地处理了持续的,确定性的并发。



正确有效地实现这个模型是一个相当大的挑战,但那是另一回事。


I've read the Wikipedia article on reactive programming. I've also read the small article on functional reactive programming. The descriptions are quite abstract.

  1. What does functional reactive programming (FRP) mean in practice?
  2. What does reactive programming (as opposed to non-reactive programming?) consist of?

My background is in imperative/OO languages, so an explanation that relates to this paradigm would be appreciated.

解决方案

If you want to get a feel for FRP, you could start with the old Fran tutorial from 1998, which has animated illustrations. For papers, start with Functional Reactive Animation and then follow up on links on the publications link on my home page and the FRP link on the Haskell wiki.

Personally, I like to think about what FRP means before addressing how it might be implemented. (Code without a specification is an answer without a question and thus "not even wrong".) So I don't describe FRP in representation/implementation terms as Thomas K does in another answer (graphs, nodes, edges, firing, execution, etc). There are many possible implementation styles, but no implementation says what FRP is.

I do resonate with Laurence G's simple description that FRP is about "datatypes that represent a value 'over time' ". Conventional imperative programming captures these dynamic values only indirectly, through state and mutations. The complete history (past, present, future) has no first class representation. Moreover, only discretely evolving values can be (indirectly) captured, since the imperative paradigm is temporally discrete. In contrast, FRP captures these evolving values directly and has no difficulty with continuously evolving values.

FRP is also unusual in that it is concurrent without running afoul of the theoretical & pragmatic rats' nest that plagues imperative concurrency. Semantically, FRP's concurrency is fine-grained, determinate, and continuous. (I'm talking about meaning, not implementation. An implementation may or may not involve concurrency or parallelism.) Semantic determinacy is very important for reasoning, both rigorous and informal. While concurrency adds enormous complexity to imperative programming (due to nondeterministic interleaving), it is effortless in FRP.

So, what is FRP? You could have invented it yourself. Start with these ideas:

  • Dynamic/evolving values (i.e., values "over time") are first class values in themselves. You can define them and combine them, pass them into & out of functions. I called these things "behaviors".

  • Behaviors are built up out of a few primitives, like constant (static) behaviors and time (like a clock), and then with sequential and parallel combination. n behaviors are combined by applying an n-ary function (on static values), "point-wise", i.e., continuously over time.

  • To account for discrete phenomena, have another type (family) of "events", each of which has a stream (finite or infinite) of occurrences. Each occurrence has an associated time and value.

  • To come up with the compositional vocabulary out of which all behaviors and events can be built, play with some examples. Keep deconstructing into pieces that are more general/simple.

  • So that you know you're on solid ground, give the whole model a compositional foundation, using the technique of denotational semantics, which just means that (a) each type has a corresponding simple & precise mathematical type of "meanings", and (b) each primitive and operator has a simple & precise meaning as a function of the meanings of the constituents. Never, ever mix implementation considerations into your exploration process. If this description is gibberish to you, consult (a) Denotational design with type class morphisms, (b) Push-pull functional reactive programming (ignoring the implementation bits), and (c) the Denotational Semantics Haskell wikibooks page. Beware that denotational semantics has two parts, from its two founders Christopher Strachey and Dana Scott: the easier & more useful Strachey part and the harder and less useful (for software design) Scott part.

If you stick with these principles, I expect you'll get something more-or-less in the spirit of FRP.

Where did I get these principles? In software design, I always ask the same question: "what does it mean?". Denotational semantics gave me a precise framework for this question, and one that fits my aesthetics (unlike operational or axiomatic semantics, both of which leave me unsatisfied). So I asked myself what is behavior? I soon realized that the temporally discrete nature of imperative computation is an accommodation to a particular style of machine, rather than a natural description of behavior itself. The simplest precise description of behavior I can think of is simply "function of (continuous) time", so that's my model. Delightfully, this model handles continuous, deterministic concurrency with ease and grace.

It's been quite a challenge to implement this model correctly and efficiently, but that's another story.

这篇关于什么是(功能性)反应式编程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆