【问题标题】:Event handling in Netwire compared to conventional FRP frameworks与传统 FRP 框架相比,Netwire 中的事件处理
【发布时间】:2013-01-17 05:49:31
【问题描述】:

大多数 Haskell FRP 框架(如 AFRP、Yampa 和 Reactive-banana)在连续时变函数和离散函数之间有所区别。通常他们称之为行为和事件。

Netwire 是一个例外,它使用抑制幺半群来模拟事件。这种方法的优缺点是什么?

我对将 FRP 应用于机器人控制特别感兴趣。例如,本文http://haskell.cs.yale.edu/?post_type=publication&p=182 展示了一种使用事件在 FRP 中对任务和 HSM 抽象进行编码的方法。可以直接翻译成Netwire吗?

【问题讨论】:

    标签: events haskell frp reactive-banana


    【解决方案1】:

    将事件作为潜在抑制信号的优势在于,它允许您非常简洁地编码最复杂的反应公式。想象一个开关,按下时显示“是”,否则显示“否”:

    "yes" . switchPressed <|> "no"
    

    这个想法是switchPressed 在其相应事件发生时就像身份线一样,否则就被禁止。这就是&lt;|&gt; 出现的地方。如果第一根线被禁止,它会尝试第二根。这是一个假设的机器人手臂,由两个按钮(左右)控制:

    robotArm = integral_ 0 . direction
    direction =
        ((-1) . leftPressed  <|> 0) +
        (1    . rightPressed <|> 0)
    

    虽然机器人手臂是假设的,但此代码不是。这确实是您在 Netwire 中编写的方式。

    【讨论】:

    • (-1)(+1) 有不同的类型;但我不确定你打算让他们拥有什么类型,所以我不愿意编辑你的代码。
    • 这是否意味着所有事件必须具有相同的类型?即,e in Wire e m a b?谈到你的例子,如果我想通过在一个轴上移动手臂和触控笔事件来对按键做出反应,这给了我两个坐标?
    • 确实,写1 而不是(+1)。只是为了让代码更漂亮。 =) e 类型是抑制幺半群。它与Either e a 中的e 具有相同的作用。事件没有特定类型。事件的概念必然会受到抑制。事件线通常在事件发生时起到标识线的作用,否则会被禁止。
    • @DmitryVyal:我一定错过了你的问题。对于事件连线,将(.) 视为“和”,将(&lt;|&gt;) 视为(包括)“或”。例如,如果e1e2 都发生,则线w . e1 . e2 的作用类似于w。如果e1e2 中的至少一个发生,则线w . (e1 &lt;|&gt; e2) 的作用类似于w
    【解决方案2】:

    经过一些试验,我已经实现了我需要的行为。基本上,您编写了一个自定义抑制剂类型,它可以捕获您需要的事件概念。在我的情况下是

    data Inhibitor = Done | Timeout | Interrupt deriving Show
    

    Done 表示正常完成,其余构造函数表示某种错误。

    之后,您可以编写所需的任何自定义组合器。就我而言,我需要一种方法来停止计算并进一步发出错误信号:

    timeout deadline w | deadline <= 0 = inhibit Timeout
                       | otherwise = mkGen $ \dt a -> do
                           res <- stepWire w dt a
                           case res of
                             (Right o, w') -> return (Right o, timeout (deadline - dt) w')
                             (Left e, _)  -> return (Left e, inhibit e)
    

    这是 switchBy 的一种变体,它允许您更改一次电线。注意,它传递了一条新线的禁止信号:

    switchOn new w0 =
        mkGen $ \dt x' ->
            let select w' = do
                    (mx, w) <- stepWire w' dt x'
                    case mx of
                      Left ex -> stepWire (new ex) dt x'
                      Right x -> return (Right x, switchOn new w)
            in select w0
    

    这是 (-->) 的变体,它抓住了中断任务链的想法。

    infixr 1 ~>
    
    w1 ~> w2 = switchOn ( \e -> case e of
                             Done -> w2
                             _ -> inhibit e
                        ) w1
    

    【讨论】:

      猜你喜欢
      • 2010-09-15
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      • 2015-04-05
      • 2015-01-19
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      相关资源
      最近更新 更多