16

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

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

4

2 回答 2

17

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

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

事实上,我有一些使用 FRP 的很好的经验,正是你所说的“更轻”:简单的 GUI 程序。我使用响应式香蕉和 wxWidgets 编写了一些非常简单的小图形程序。我发现生成的代码比等效的基于回调的代码更简单、更容易编写和更容易阅读。

Reactive Banana 也可以用于音乐之类的东西,因此它显然具有广泛的适用性。除了使用它进行 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 等现有框架所做的——它们都没有使用反应式编程风格,但它们仍然很容易使用。

于 2012-11-21T05:24:24.193 回答
2

除了“简单”的 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.

它工作得很好。不需要镜片、玻璃钢或其他任何“异国情调”的东西。

于 2012-11-30T04:16:43.773 回答