关于haskell:为什么FRP将时间视为价值因素?

Why does FRP consider time as a factor for values?

行为被普遍定义为"时变值"s1。

为什么?时间是不同值的依赖性/参数是非常罕见的。

我对FRP的直觉是将行为作为事件变化值来代替;它更常见,更简单,我提出了一个更有效的想法,并且具有足够的可扩展性来支持时间(勾选事件)。

例如,如果编写计数器,则不关心时间/相关时间戳,只关心"增加按钮已单击"和"减少按钮已单击"事件。
如果你写了一个游戏并且想要一个位置/力量行为,你只关心Wasd/箭头键持有的事件等(除非你禁止你的玩家在下午向左移动;多么不公平!).

那么:为什么时间是一个考虑因素呢?为什么是时间戳?为什么有些库(如reactive-bananareactive会把它扩展到拥有FutureMoment值的程度?为什么要使用事件流而不只是响应事件发生?所有这些似乎都过于复杂化了一个简单的想法(事件变化/事件驱动的价值);收益是什么?我们在这里解决什么问题?(如果可能的话,我还想得到一个具体的例子和一个精彩的解释)。

已经定义了1种行为,所以这里,这里,这里…&几乎所有我遇到的地方。


因为这是我能想到的最简单的方法,可以对行为的概念给出精确的表示(实现独立的含义),包括我想要的操作种类,包括区分和集成,以及跟踪一个或多个其他行为(包括但不限于用户生成的行为)。

Why? time being the dependency/parameter for varying values is very uncommon.

我怀疑你混淆了行为的结构(配方)及其含义。例如,行为可以通过依赖于用户输入之类的东西来构造,可能还需要额外的合成转换。所以这里有食谱。然而,其含义只是时间的函数,与用户输入的时间函数相关。注意,在"函数"这个词的数学意义上,我的意思是:从域(时间)到范围(值)的(确定性)映射,而不是纯粹的程序化描述。

我见过很多问题问为什么时间很重要,为什么连续时间。如果你运用简单的规则,用表示语义学的方式给出一个数学意义(对于函数式程序员来说,这是一种简单而熟悉的方式),问题就会变得更加清楚。

如果你真的想摸索FRP的本质和背后的想法,我建议你阅读我对"功能性反应式编程语言规范"的回答,并遵循指针,包括"什么是功能性反应式编程"。


Behaviors与Events的区别主要在于Behavior现在有一个值,而Event只有在新事件发生时才有一个值。

那么"现在"是什么意思呢?从技术上讲,所有的更改都是作为事件流上的推或拉语义来实现的,因此我们可能只意味着"这个Behavior的最后一个结果事件的最新值"。但在实践中,"现在"这个概念相当复杂,要简单得多。

为什么"现在"更简单的原因可以归结为API。下面是两个来自活性香蕉的例子。

  • 最终,玻璃钢系统必须始终产生某种外部可见的变化。在反应性香蕉中,这是由消耗事件流的reactimate :: Event (IO ()) -> Moment ()功能所促进的。没有办法让Behavior触发外部变化——你总是需要做一些像reactimate (someBehavior <@ sampleTickEvent)这样的事情来在具体的时间对行为进行抽样。

  • 行为是Applicatives与Events不同。为什么?好吧,假设Event是一个应用程序,考虑当我们有两个事件流fx并编写f <*> x时会发生什么:由于事件发生的时间不同,同时定义fx的可能性(几乎可以肯定)为0。因此,f <*> x总是指无用的空事件流。

    您真正想要的是f <*> x为每个缓存最新的值,并"一直"使用它们的组合值。从事件流的角度来说,这真的是一个令人困惑的概念,因此让我们考虑fx作为所有时间点的值。现在,f <*> x也被定义为对所有时间点都取值。我们刚刚发明了Behavior


  • Conal Elliott的推拉式玻璃钢论文描述了事件变化数据,其中唯一有趣的时间点是事件发生时。Reactive事件变化数据是当前值,下一个Event将改变它。Event是在Reactive数据发生变化时的Future点。

    1
    2
    data Reactive a = a ‘Stepper ‘ Event a
    newtype Event a = Ev (Future (Reactive a))

    Future不需要与之相关联的时间,它只需要表示尚未发生的价值的概念。例如,在带有事件的不纯语言中,未来可以是事件句柄和值。当事件发生时,设置值并提升句柄。

    Reactive a在任何时间点上都对a有价值,那么为什么我们需要Behaviors?让我们做一个简单的游戏。在用户按下wasd键之间,在施加的力的加速下,字符仍在屏幕上移动。角色在不同时间点的位置是不同的,即使在中间时间没有发生任何事件。这就是Behavior所描述的——它不仅在所有时间点都有一个值,而且在所有时间点它的值都可能不同,即使没有干预事件。

    描述Behavior的一种方法是重复我们刚才所说的。Behaviors是在事件之间可以改变的事物。在事件之间,它们是随时间变化的值或时间函数。

    1
    type Behavior a = Reactive (Time -> a)

    我们不需要Behavior,我们可以简单地为时钟计时添加事件,并根据这些计时事件编写整个游戏中的所有逻辑。对于一些开发人员来说,这是不可取的,因为声明游戏内容的代码现在与提供如何实现的代码混合在一起。BehaviorS允许开发者在游戏描述的时变变量和执行该描述的引擎的实现之间分离这种逻辑。