2017-02-19 89 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