反应性香蕉:绑定

Reactive Banana: Bindings

我正在开发基于小型终端的 UI,我想使用 Reactive Banana 来描述交互。我唯一感兴趣的外部事件是用户是否按下了某个键。

根据我从 Frameworks 文档中收集到的信息,我可以使用轮询来获取终端输入缓冲区的状态,或者将 "event handler" 传递给 Reactive Banana。我更喜欢后者,但我发现事件处理部分令人困惑。我将如何准确描述 getChar 的事件驱动版本?最后,我想在 "Event Key" 流上进行操作。

我查看了 SDL 和 wx 绑定,但我没有发现它们有多大帮助,因为它们充斥着与库相关的特性,我非常希望能更简洁地解释事件处理程序、事件loops 和 Reactive Banana 混合在一起。

事实证明,使用 Reactive Banana 处理外部事件非常灵活和简单。所需要的只是创建一个带有 "newAddHandler" 的事件处理程序,它由两部分组成,一个 "AddHandler" 可以使用 reactimate 函数从中创建事件,以及一个必须由胶水调用的处理程序将 Reactive Banana 桥接到框架的代码(绑定)(在我的例子中,我只是将 getChar 的结果提供给处理程序)。

这是一个回显击键的示例代码:

echo = do
  (keyEventHandler, fire) <- newAddHandler

  -- Network Specification (echo keyboard input)
  let networkDescription =
      fromAddHandler keyEventHandler >>= -- Create event stream from handler
      reactimate . fmap print -- Map print over event stream

  compile networkDescription >>= actuate 

  -- Event Loop
  hSetBuffering stdin NoBuffering   
  forever $ do
      ready <- hReady stdin
      if ready
          then getChar >>= fire -- Create keyboad event
          else return ()

reactive banana 的好处在于回调函数 "fire" 可以从任何上下文中调用。因此,事件循环也可以在线程中 运行 或从 C 库中调用。海因里希对 How to implement a game loop in reactive-banana?.

的回答可以找到更多相关信息

然而,在不进行轮询的情况下捕获任意键盘输入事件并不像我想的那么容易,POSIX 不允许这样做(如果我没记错的话),即使这样做代码也不可移植. 另请注意,在 Windows 机器上,您必须按回车键,我仍然需要找到解决该问题的方法。已找到有关此问题的更多信息 at the Haskell bugtracker