FRP是实现大多数"event-driven"事物的正确方法吗?



在我对Haskell的第一印象中,它是一种可以很好地处理"先执行后结果"的语言。但我找不到如何实现"事件驱动"的东西,比如游戏或HTTP/FTP/TCPSocket服务器。

这个问题是在我读了一些关于FRP的论文后得到回答的,包括Yampa和它创建的FPS游戏(Frag)。FRP似乎是一个很好的模型,可以实现3D游戏等"重"事件驱动的东西,但事件驱动的应用程序(如HTTP服务器或普通桌面GUI程序)如何?如果我使用FRP来实现所有这些事情,会出现什么缺点?

FRP是一种非常通用的技术,几乎可以肯定地用于实现任何通常使用事件的东西。在FRP的经典再现中,的核心抽象之一是事件。不同之处在于,您不是通过回调单独操作事件,而是对事件的进行操作。

您应该能够根据事件流呈现任何正常的事件驱动代码;唯一的困难是将流与现有的外部代码(如GUI工具包)绑定;然而,这与其说是棘手,不如说是乏味。因此,我认为没有任何根本问题阻止您在任何使用不同语言的事件的地方使用FRP。

事实上,我已经有了一些很好的经验,使用FRP来实现你所说的"更轻":简单的GUI程序。我使用了带有wxWidgets的反应香蕉来编写一些非常简单的小图形程序。我发现生成的代码比同等的基于回调的代码更简单、更容易写、更容易读。

活性香蕉也可以用于音乐等用途,因此它显然广泛适用。除了使用它进行GUI编程外,我还没有尝试过任何东西,但其他人已经尝试过了,所以它必须是可能的。

此外,您应该查看Elm,它是一种ML风格的语言,用于使用FRP实现web应用程序。它生成您需要的一切:HTML、CSSJavaScript。我相信它甚至可以处理与服务器的通信。我还没试过,但它看起来很好看。

因此,人们显然在广泛的领域使用FRP,包括那些不"重"的领域。但这并不意味着你应该在任何地方使用它!

首先,可能会出现不可预测的空间和时间行为。我知道Reactive Banana和Elm的创作者都付出了很多努力来减少这些,但我怀疑仍然存在一些风险。我知道我在玩Reactive Banana WX时有一些非常奇怪的空间泄漏,所以这肯定是需要注意的。与您习惯使用的事件驱动代码相比,使用FRP处理这些问题可能更困难。当然,我在标准JavaScript中遇到过莫名其妙的内存泄漏,所以非FRP代码也不能幸免!

另一个考虑因素是,FRP可能不是您特定任务的最佳或最清晰的抽象。虽然这对于必须完全响应的事情来说很好,但对于非常简单的代码(如web服务器)呢?(我的意思是,在不同的请求中,简单的请求可能彼此之间的交互不太紧密。)我认为有一个使用基于FRP的编程模型处理大量请求的web框架是可能的;我只是不认为这是最佳。

事实上,我的理解是,GHC IO系统实际上已经是事件驱动的,所以你可以用标准的编程风格编写web服务器,并免费使用事件。因此,对于web服务器代码来说,更简单的底层抽象可能是更好的选择。我相信像Snap和Yesod这样的现有框架就是这样做的——它们都不使用反应式编程风格,但使用起来仍然很愉快。

您不需要使用"简单"Haskell之外的任何东西来实现事件驱动的游戏。我目前正在使用Haskell编写一个具有以下(非常高级)"架构"的FPS:

uiMake :: IO ([UIEvent],UIState)
uiTick :: UIState -> [ApEvent] -> IO ([UIEvent],UIState)
apMake :: ([ApEvent],ApState)
apTick :: ApState -> [UIEvent] -> ([ApEvent],ApState)
-- UIState = The state of the UI
-- ApState = The state of the application (game)
-- UIEvent = Key presses, screen resolution changes etc.
-- ApEvent = Entity movements etc.

它非常有效。不需要镜片、玻璃钢或任何其他"异国情调"的东西。

相关内容

  • 没有找到相关文章

最新更新