我认为使用信号/行为抽象而不是 elm 风格的信号没有任何好处。正如您所指出的,可以在信号/行为 API 之上创建一个仅信号 API(还没有准备好使用,但请参阅https://github.com/JohnLato/impulse/blob/dyn2/src/以Reactive/Impulse/Syntax2.hs为例)。我很确定也可以在 elm 风格的 API 之上编写信号/行为 API。这将使这两个 API 在功能上等效。
WRT 效率,使用仅信号 API,系统应该具有一种机制,其中只有具有更新值的信号才会导致重新计算(例如,如果您不移动鼠标,FRP 网络将不会重新计算指针坐标并重绘屏幕)。如果这样做了,我认为与信号和流方法相比,不会有任何效率损失。我很确定 Elm 是这样工作的。
我不认为连续行为问题在这里(或根本没有)有任何区别。人们所说的行为是随时间连续的,是指它们在任何时候都是被定义的(即它们是连续域上的函数);行为本身不是连续函数。但我们实际上并没有办法随时对行为进行采样;它们只能在对应于事件的时间被采样,所以我们不能使用这个定义的全部力量!
从语义上讲,从这些定义开始:
Event == for some t ∈ T: [(t,a)]
Behavior == ∀ t ∈ T: t -> b
由于只能在定义事件的时间对行为进行采样,因此我们可以创建一个新域TX
,其中是定义事件TX
的所有时间的集合t
。现在我们可以将 Behavior 定义放宽为
Behavior == ∀ t ∈ TX: t -> b
不失去任何权力(即,这相当于我们 frp 系统范围内的原始定义)。现在我们可以枚举所有时间以TX
将其转换为
Behavior == ∀ t ∈ TX: [(t,b)]
除了域和量化外,它与原始Event
定义相同。现在我们可以改变Event
to的定义域TX
(通过 的定义TX
),以及Behavior
(从 forall 到 for some)的量化,我们得到
Event == for some t ∈ TX: [(t,a)]
Behavior == for some t ∈ TX: [(t,b)]
现在Event
和Behavior
在语义上是相同的,因此它们显然可以在 FRP 系统中使用相同的结构来表示。在这一步我们确实丢失了一些信息;如果我们不区分Event
并且Behavior
我们不知道每次都Behavior
定义了 a ,但实际上我认为这并不重要。IIRC 的 elm 要求s 和s 在任何时候都具有值,并且如果它没有改变,则只使用先前的值(即改变 to 的量化而不是改变 的量化t
Event
Behavior
Event
Event
forall
Behavior
)。这意味着您可以将所有内容视为一个信号,并且一切正常;它只是实现了,因此信号域正是系统实际使用的时间子集。
我认为这个想法是在一篇关于在 Java 中实现 FRP 的论文中提出的(我现在找不到,还有其他人有链接吗?),也许来自 POPL '14?凭记忆工作,所以我的大纲不如原始证明那么严格。
没有什么可以阻止您创建Behavior
由 eg定义的更多内容pure someFunction
,这仅意味着在 FRP 系统中您无法使用该额外定义性,因此更受限制的实现不会丢失任何内容。
至于时间等名义信号,请注意,使用典型的编程语言不可能实现实际的连续时间信号。由于实现必然是离散的,因此将其转换为事件流是微不足道的。
简而言之,我认为仅使用信号不会丢失任何东西。