在我对Haskell的第一印象中,它是一种语言可以非常好地处理“执行然后结果”的事情。但我找不到如何实现游戏或HTTP / FTP / TCPSocket服务器等“事件驱动”的东西。
在我阅读了一些关于FRP的论文后,这个问题得到了解答,包括Yampa和由它创建的FPS游戏(Frag)。看起来FRP是一个很好的模型来实现像3D游戏这样的“重型”事件驱动的东西,但是像 slighter 事件驱动的应用程序如HTTP服务器或普通的桌面GUI程序呢?如果我使用FRP来实现所有这些东西会出现什么缺点?
答案 0 :(得分:17)
FRP是一种非常通用的技术,几乎可以肯定用于实现通常使用事件的任何东西。在FRP的经典演绎中,其中一个核心抽象是事件。不同之处在于,您不是使用回调单独操作事件,而是使用 streams 事件进行操作。
您应该能够根据事件流呈现任何正常的事件驱动代码;唯一的困难是将流绑定到现有的外部代码,如GUI工具包;然而,这比狡猾更乏味。因此,我没有看到任何根本问题阻止您在任何地方使用FRP来使用其他语言的事件。
事实上,我已经有了一些使用FRP的好经验,正是你所谓的“更轻”:简单的GUI程序。我已经使用reactive banana和wxWidgets来编写一些非常简单的小图形程序。我发现生成的代码比基于回调的等效代码更简单,更容易编写和更容易阅读。
活性香蕉也可以用于music之类的东西,所以它显然广泛适用。我没有尝试过除GUI编程以外的任何东西,但其他人必须这样做。
此外,您应该查看Elm,这是一种ML风格的语言,用于实现FRP的Web应用程序。它生成您需要的一切:HTML,CSS 和 JavaScript。我相信它甚至可以处理与服务器的通信。我没试过,但看起来很不错。
因此,人们显然在各种领域使用FRP,包括那些不“重”的领域。但这并不意味着你应该在任何地方使用它!
首先,可能会出现不可预测的空间和时间行为。我知道Reactive Banana和Elm的创造者都在努力减少这些,但我怀疑还存在一些风险。我知道在玩Reactive Banana WX时我有一些非常奇怪的空间泄漏,所以这当然值得注意。使用FRP处理这些问题可能比使用事件驱动代码更困难。当然,我已经使用标准JavaScript进行了无法解释的内存泄漏,因此非FRP代码也不能免于此!
另一个考虑因素是FRP可能不是您特定任务的最佳或最清晰的抽象。虽然它非常适合那些必须完全被动的东西,但是代码非常简单,比如Web服务器呢? (我的意思是简单,因为在不同的请求中可能不会彼此过于密切地交互。)我想有一个Web框架可以使用基于FRP的编程模型处理大量请求。我只是认为它不是最佳。
事实上,我的理解是GHC IO系统实际上已经是事件驱动的,因此您可以使用标准编程风格编写Web服务器,并获得免费使用事件的好处。因此,对于Web服务器代码,更简单的底层抽象可能是更好的选择。我相信Snap和Yesod这样的现有框架都没有使用反应式编程风格,但两者仍然可以使用。
答案 1 :(得分: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.
效果很好。不需要镜片,FRP或其他任何“异国情调”。