是“信号”吗?函数式反应式编程的表示正确吗?

发布于 2024-12-05 02:10:25 字数 456 浏览 2 评论 0原文

我一直在研究 FRP 并发现了许多不同的实现。我见过的一种模型我将其称为“信号”表示。这一本质将事件和行为结合成一个实体。

首先,信号是一个对象,其值是一种行为。其次,信号具有一个事件“流”,可以将其视为标准数据结构并对其进行操作(您可以在信号上使用“每个”、“映射”和“过滤器”等来定义事件的反应方式)。例如,我可以这样做(其中“时间”是时间的信号表示):

time.each { t => print(t) } // every time there is a 'tick' the current time is printed
a = time * 5 //where 'a' would be a dynamic value always up to date with time

FRP 的这种表示正确还是有任何问题?我非常喜欢这种工作方式,也喜欢它的个人描述是多么简单,但我不确定它是否正确。

I have been researching FRP and found a bunch of different implementations. One model I have seen is one I will refer to as the 'Signal' representation. This essential combines Events and Behaviours into one entity.

Firstly, a Signal is an object thats value is a Behaviour. Secondly, a Signal has an Event 'stream' that can be seen and operated on as a standard data structure (you can use 'each', 'map' and 'filter' etc on the Signal to define how Events are reacted to). For example I can do this (where 'time' is a Signal representation of time):

time.each { t => print(t) } // every time there is a 'tick' the current time is printed
a = time * 5 //where 'a' would be a dynamic value always up to date with time

Is this representation of FRP correct or are there any problems? I quite like the way this works and also how simple it is to describe personally but I'm not sure its right.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆で 2024-12-12 02:10:25

不幸的是,将“事件”和“行为”合并为单个实体“信号”的效果并不那么好。

据我所知,大多数基于信号的 FRP 实现最终都会创建一个额外的类似“事件”的类型,

type Event a = Signal (Maybe a)

因此,事件的概念不会消失,并且没有真正的简化。事实上,我认为信号类型是语义的复杂化。信号之所以受欢迎只是因为它们更容易实现。

反对信号的主要论点是它们不能代表连续时间行为,因为它们必须迎合离散事件。在 Conal Elliott 的最初设想中,行为是时间的简单连续函数。

type Behavior a = Time -> a
-- = function that takes the current time as parameter and returns
--   the corresponding value of type  a

相比之下,信号始终是离散的,并且通常与固定的值相关联。时间步。 (可以在可变时间步信号之上实现事件和行为,但它本身并不是一个好的抽象。)将此与事件流进行比较,

type Event a = [(Time,a)]
-- list of pairs of the form (current time, corresponding event value)

其中各个事件不一定以规则的时间间隔发生。

区分行为和事件的论据是它们的 API 完全不同。要点是它们具有不同的产品类型:

(Behavior a , Behavior b) = Behavior (a,b)
(Event a    , Event b   ) = Event (a :+: b)

换句话说:一对行为与成对行为相同,但一对事件与来自任一组件/通道的事件相同。另一点是,有两个操作

(<*>) :: Behavior (a -> b) -> Behavior a -> Behavior b
apply :: Behavior (a -> b) -> Event a    -> Event b

具有几乎相同的类型,但语义却截然不同。 (第一个参数在第一个参数更改时更新结果,而第二个则不会。)

总结一下:信号可用于实现 FRP,并且对于尝试新的实现技术很有价值,但行为和事件对人们来说是更好的抽象谁只想使用玻璃钢。

(全面披露:我在 Haskell 中实现了一个名为 reactive-banana 的 FRP 库。)

Unfortunately, coalescing "event" and "behavior" into a single entity "signal" doesn't work so well.

Most signal-based FRP implementations that I know end up creating an additional "event"-like type along the lines of

type Event a = Signal (Maybe a)

So, the concept of events doesn't go away, and there is no real simplification. In fact, I would argue that the signal type is a semantic complification. Signals are only popular because they are easier to implement.

The main argument against signals is that they cannot represent continuous time behaviors, because they have to cater to the discrete events. In Conal Elliott's original vision, behaviors were simple continuous functions of time

type Behavior a = Time -> a
-- = function that takes the current time as parameter and returns
--   the corresponding value of type  a

In contrast, signals always are always discretized and usually associated with a fixed time step. (It is possible to implement both events and behaviors on top of a variable time step signal, but it's not a good abstraction by itself.) Compare this to an event stream

type Event a = [(Time,a)]
-- list of pairs of the form (current time, corresponding event value)

where the individual events don't necessarily occur in regularly spaced time intervals.

The argument for the distinction between behaviors and events is that their API is quite different. The main point is that they have different product types:

(Behavior a , Behavior b) = Behavior (a,b)
(Event a    , Event b   ) = Event (a :+: b)

In words: a pair of behaviors is the same as a behavior of pairs, but a pair of events is the same as an event from either component/channel. Another point is that there are two operations

(<*>) :: Behavior (a -> b) -> Behavior a -> Behavior b
apply :: Behavior (a -> b) -> Event a    -> Event b

that have almost the same type, but quite different semantics. (The first updates the result when the first argument changes, while the second doesn't.)

To summarize: signals can be used for implementing FRP and are valuable for experimenting with new implementation techniques, but behaviors and events are a better abstraction for people who just want to use FRP.

(Full Disclosure: I have implemented an FRP library called reactive-banana in Haskell.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文