2017-02-19 46 views
4

我正在閱讀Conal Elliot的論文"Declarative Event-Oriented Programming",其中的例子是使用現在已經過時的Fran庫編寫的。ifB在反應香蕉中的實現

當我學習FRP時,我試着用反應式香蕉來實現這些例子。我似乎沒有這個問題(但必須認爲很多 :))。唯一我不明白的是如何正確翻譯Fran的ifB

它似乎有這種類型的簽名:

ifB :: Behavior Bool -> Behavior a -> Behavior a -> Behavior a 

但反應香蕉只有switchB對於這樣的事情。

目前我設法通過添加將用於切換的行爲,這樣的一個額外的「觸發」事件來做到這一點:

ifB :: MonadMoment m => Event b -> BoolB -> Behavior a -> Behavior a -> m (Behavior a) 
ifB trigger condB b1 b2 = switchB b2 (switcherB <@ trigger) 
    where switcherB = (\x -> if x then b1 else b2) <$> condB 

我不知道這是否是一個正確和良好的解決方案。它是高性能的嗎? 下面是從使用ifB論文片段:

editCPoint :: User -> S.Point2 -> CPoint 
editCPoint u p0 = (pos, closeEnough) 
    where 
    pos, lastRelease :: Point2B 
    -- vvv this is the ifB in question! 
    pos = ifB grabbing (mouse u) lastRelease 
    lastRelease = stepper p0 (release ‘snapshot_‘ pos) 

    closeEnough, grabbing :: BoolB 
    closeEnough = distance2 pos (mouse u) <* grabDistance 
    grabbing = stepper False (grab -=> True .|. release -=> False) 

    grab, release :: Event() 
    grab = lbp u ‘whenE‘ closeEnough 
    release = lbr u ‘whenE‘ grabbing 

grabDistance :: RealB 
grabDistance = 2 * pointSize 

我設法得到這個片段與無功香蕉的工作,通過使用我的實施ifB,所以它得到定期更新餵養它一個cursor move事件。我試圖餵它只有鼠標按下/釋放事件作爲觸發器切換,它不能正常工作...

我做錯了嗎?有關如何做得更好的建議?

回答

4

BehaviorApplicative情況下,這足以實現ifB沒有動態切換:

ifB :: Behavior Bool -> Behavior a -> Behavior a -> Behavior a 
ifB bB bT bF = (\b t f -> if b then t else f) <$> bB <*> bT <*> bF 

或者,使用boolData.Bool

ifB :: Behavior Bool -> Behavior a -> Behavior a -> Behavior a 
ifB bB bT bF = bool <$> bF <*> bT <*> bB 
+1

非常感謝你,它再次尚未那一刻當我想到「爲什麼我沒有看到這個?」在學習Haskell時經常會碰到我。我喜歡這個 :) – dimsuz