2017-02-19 1 views
4

Je lis l'article de Conal Elliot "Declarative Event-Oriented Programming" qui a ses exemples écrits en utilisant une bibliothèque Fran qui est maintenant obsolète. En apprenant la FRP, j'essaie de mettre en œuvre ces exemples en utilisant réactif-banane. Je semble n'avoir aucun problème avec ceci (mais dois penser beaucoup :)). La seule chose que je ne comprends pas est comment traduire correctement les ifB de Fran.Mise en œuvre de ifB dans la banane réactive

Il semble avoir cette signature de type:

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

Mais réactive la banane n'a que switchB pour ce genre de chose.

Actuellement, je réussi à le faire en ajoutant un événement « déclencheur » supplémentaire qui sera utilisé pour changer les comportements, comme celui-ci:

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 

Je ne suis pas sûr que ce soit une solution correcte et bon. Est-ce performant? ci-dessous est un extrait du papier qui utilise 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 

J'ai réussi à obtenir cet extrait de travailler avec la banane-réactive, en utilisant ma mise en œuvre de ifB et nourrir un événement cursor move il est mis à jour régulièrement. J'ai essayé de le nourrir seulement les événements press/release de souris comme déclencheurs pour la commutation et cela n'a pas fonctionné correctement ...

Ai-je fait le mal? Des conseils sur comment faire mieux?

Répondre

4

Behavior a une instance Applicative, ce qui est suffisant pour mettre en œuvre ifB sans commutation dynamique:

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 

Ou, en utilisant bool de Data.Bool:

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

Merci beaucoup, il est encore une fois ce moment quand je pense "pourquoi n'ai-je pas vu ça?" Ça m'arrive souvent quand j'apprends Haskell. J'aime ça :) – dimsuz