[英]Event handling in Netwire compared to conventional FRP frameworks
大多數Haskell FRP框架如AFRP,Yampa和Reactive-banana在連續時變函數和離散函數之間產生差異。 通常他們稱他們為行為和事件。
一個例外是Netwire,它使用抑制monoid來模擬事件。 這種方法的優點和缺點是什么?
特別是,我對FRP在機器人控制中的應用感興趣。 例如,本文http://haskell.cs.yale.edu/?post_type=publication&p=182顯示了一種使用事件對FRP中的任務和HSM抽象進行編碼的方法。 這可以直接翻譯成Netwire嗎?
事件作為潛在抑制信號的優勢在於它允許您非常簡潔地編碼大多數甚至復雜的反應式。 想象一下,按下時顯示“是”的開關,否則顯示“否”:
"yes" . switchPressed <|> "no"
這個想法是,如果發生相應的事件, switchPressed
就像身份線一樣,否則就會禁止。 這就是<|>
進來的地方。如果第一根電線禁止,它會嘗試第二根電線。 這是一個由兩個按鈕(左和右)控制的假想機器人手臂:
robotArm = integral_ 0 . direction
direction =
((-1) . leftPressed <|> 0) +
(1 . rightPressed <|> 0)
雖然機器人手臂是假設的,但這個代碼不是。 這真的是你在Netwire中寫這個的方式。
經過一些試驗,我已經實現了我需要的行為。 基本上,您編寫了一個自定義抑制器類型,它可以捕獲您需要的事件概念。 就我而言
data Inhibitor = Done | Timeout | Interrupt deriving Show
完成意味着正常完成,其余構造函數表示某種錯誤。
之后,您可以編寫所需的任何自定義組合器。 在我的情況下,我需要一種方法來停止計算並進一步發出錯誤信號:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.