sea*_*owg 4 haskell programming-languages functional-programming scala frp
我正在玩FRP,并且想知道应该如何公开处理事件"发生"的行为.通过这个,我的意思是程序员应该能够在FRP上下文中执行以下操作:
event.occur(now, 5)
Run Code Online (Sandbox Code Playgroud)
我从未在任何FRP论文中看到这样的例子,对我来说感觉不对.我觉得FRP框架应该真正隐藏这种类型的动作,并且事件的发生应该仅在幕后发生.我在想这个是正确的吗?
为了澄清,我的方法是"发生"只能由Event类本身访问.如果需要某些外部源的抽象(例如鼠标),可以通过扩展Event类来构建.通过这种方式,所有处理事件创建的逻辑都被抽象出来了.
好吧,如果FRP库公开了一种绑定到外部事件的方法 - 例如现有的基于事件的框架 - 那么它必须提供与此相当的功能,否则它就无法与外部世界交互.
但问题是:"外部"是什么意思?FRP系统本身通常被认为是纯粹的,因此event.occur(now, 5)从FRP系统内部执行副作用代码的想法甚至没有意义.通常,当然,一个设施,响应于FRP事件执行这样的代码被提供,但是这通常不采取作为纯编程模型的一部分,而作为一种设施接口的网络作为一个整体与外部世界.
因此,在我看来,有两种方法可以解释这个问题:
实际上,即使您明确禁止它,也可能会产生类似#2的东西:考虑设置事件以便switchToWindow 3在事件buttonClicked触发时执行,例如(使用反应性香蕉表示法):
reactimate (switchToWindow 3 <$ buttonClicked)
Run Code Online (Sandbox Code Playgroud)
并说我们有一个活动
newWindowFocused :: Event Int
Run Code Online (Sandbox Code Playgroud)
我们设置的反应导致newWindowFocused事件触发,即使由于事件而执行的内部代码中的触发事件被阻止也是如此.
现在,我到目前为止所说的一切只涉及"外部"事件:那些没有用纯粹的FRP表达的事件,而是明确地创建用于表示在FRP系统之外的外部世界中发生的事件.如果你问是否应该有一个设施在纯粹定义的事件中引起特殊事件,那么我的回答是:绝对不是!这破坏了系统的意思,因为突然之间fmap f (union e1 e2)并不意味着"与价值发生f x时,无论是e1或e2与价值发生x",而是"与价值发生f x时,无论是e1或e2与价值发生x......或者当一些外部代码随机决定解雇它".
这样的设施不仅会对FRP系统的行为进行推理而基本上没有意义,1它也违反了参照透明度:如果你构造了两个相当于的事件fmap f (union e1 e2),那么你可以通过触发一个并注意到另一个没有来区分它们.发生了.在所有情况下fmap g (union e1 e2),你根本无法阻止这种情况:想象一下,在哪里f计算相同的函数g; 功能上的平等是不可判定的:)
当然,完全可以用不纯的语言实现FRP,但我认为提供一种违反FRP系统本身参考透明度的方法是一件非常糟糕的事情,因为它毕竟是一个纯粹的模型.
如果我理解正确的话,你在API中解决这个缺陷的方法(即occur公开暴露,打破等同事件的引用透明度等等,就像我上面谈到的那样)将是occur你的Event班级内部,所以它不能从外面使用.我同意,如果你需要occur内部,这是正确的解决方案.我也同意,如果外部事件的实现是通过子类化完成的,那么将它暴露给子类是合理的Event.这属于"外界粘合剂",它超出了FRP模型本身的范围,因此完全可以让它以这种方式"打破规则" - 毕竟,这基本上就是它的原因:令人不安系统有副作用:)
所以,最后:
不,事件不应暴露此接口.
是的,你认为这是正确的:)
1当然,你可以说,外部事件做这个句号,作为系统的整体行为最终取决于迷上了外界的"边缘",但是这是不是真的:是的,你不能真的假设外部事件本身,但你仍然可以依靠你建立的一切来遵守他们的结构规律.为每个活动提供"外部射击"设施意味着没有任何建筑有任何法律.