【问题标题】:reactive-banana: How to create an AddHandler?反应香蕉:如何创建一个 AddHandler?
【发布时间】:2011-12-25 22:06:58
【问题描述】:

我目前正在尝试通过 Heinrich Apfelmus 的 reactive-banana 了解 FRP,与我看过的其他库相比,它似乎是一个文档齐全且简单的库。

但是,我无法理解AddHandler 类型。假设我想使用GLFW 来获得鼠标按钮点击,这样我就有了eMouseButton :: Event () 之类的东西。查看示例,似乎我不得不以某种方式使用fromAddHandler,但我不知道如何组装该AddHandler 参数。我想我必须以某种方式使用newAddHandler,但是如何使用?

我想举个例子说明如何将reactive-banana 连接到wx 以外的其他东西会很有帮助。

【问题讨论】:

    标签: haskell reactive-programming reactive-banana


    【解决方案1】:

    newAddHandler 是这样使用的:

    do (addHandler, fire) <- newAddHandler
       ...
    

    addHandler 是要传递给 reactive-banana 的 AddHandler,fire 是触发事件的 a -&gt; IO () 类型的函数(其中 a 是您的事件类型)。 p>

    例如,您可能会安装 fire 作为 GLFW 鼠标按钮事件的回调,如下所示:

    registerMouseButton :: IO (Event MouseButton)
    registerMouseButton = do
      (addHandler, fire) <- newAddHandler
      setMouseButtonCallback $ \button _ -> fire button
      fromAddHandler addHandler
    

    (我没有使用 GLFW 的经验,所以我不确定 setMouseButtonCallback 回调的第二个参数是什么——如果它很重要,你需要适当地修改这个实现。)

    AddHandler 只是一个函数,它接受一个回调 - a -&gt; IO () - 并将其注册到相关事件;然后它返回(从IO 内)一个IO () 操作,用于注销这个处理程序,使complete definition of AddHandler 如下所示:

    type AddHandler a = (a -> IO ()) -> IO (IO ())
    

    那么newAddHandler 是从哪里来的呢?很简单:newAddHandler 维护一个事件的处理程序列表,并在执行fire x 时激活它们。

    如果像 GTK+ 和许多其他常用工具包一样,您的工具包已经具备注册和注销多个事件处理程序的功能,则不需要 newAddHandler;如果是这样,您应该编写自己的AddHandler 实现。但是如果它只支持一个回调,你应该使用newAddHandler

    请注意,您永远不需要将AddHandlers 暴露给使用 FRP 的代码本身;它们只是用于从外部输入创建Events 的内部粘合剂。

    【讨论】:

    • 终于成功了!谢谢。
    • 哎呀——我上次使用带有 GUI 工具包的响应式香蕉时,我写了一个短的(约 30 行)绑定到 GTK+,它确实有这个功能;我没有真正使用过 wxWidgets,但假设它也使用过,因为为 GTK+ 实现 AddHandler 非常自然 :) 经过进一步调查,它没有;我已经更正了我的答案。
    • @bzn:基本上,wxWidgets 没有提供再次注销特定事件处理程序的方法,这就是我必须使用newAddHandler 实用程序的原因。
    • 有人能帮我理解 newAddHandler 在后台做什么吗?可能是作者@HeinrichApfelmus?我不太了解 do 块内的let register handler 构造,我无法弄清楚“处理程序”是如何在 let / do 块内走私的,有一种直觉认为它来自“外部”通过调用register addHandler putStrLn 然后它会触发所有负责构建 addHandler a 的 newAddHandler 代码(所有名称均取自原始库)-> 这可能是 Stack 中的新线程的问题吗?
    • 我想我做到了——确认一下就好了。感谢 Haskell 引用透明性,addHandler _is_ AddHandler register 然后 `register something pattern match with register handlerhandler 变成 something (即 putStrLn 如果您继续使用库示例)。就像我最初想到的那样,它来自外部。
    猜你喜欢
    • 2014-06-17
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 2013-06-20
    • 2013-11-09
    • 2011-09-25
    • 1970-01-01
    • 2012-06-08
    相关资源
    最近更新 更多