@@ -27,7 +27,7 @@ import Prelude hiding (mapM, mapM_, sequence, sequence_, foldl)
28import Debug.Trace (trace)
28import Debug.Trace (trace)
30−class (MonadHold t (PushM t), MonadSample t (PullM t), Functor (Event t), Functor (Behavior t)) => Reflex t where
30+class (MonadHold t (PushM t), MonadSample t (PullM t), MonadFix (PushM t), Functor (Event t), Functor (Behavior t)) => Reflex t where
31 -- | A container for a value that can change over time. Behaviors can be sampled at will, but it is not possible to be notified when they change
31 -- | A container for a value that can change over time. Behaviors can be sampled at will, but it is not possible to be notified when they change
32 data Behavior t :: * -> *
32 data Behavior t :: * -> *
33 -- | A stream of occurrences. During any given frame, an Event is either occurring or not occurring; if it is occurring, it will contain a value of the given type (its "occurrence type")
33 -- | A stream of occurrences. During any given frame, an Event is either occurring or not occurring; if it is occurring, it will contain a value of the given type (its "occurrence type")
@@ -46,7 +46,7 @@ class (MonadHold t (PushM t), MonadSample t (PullM t), Functor (Event t), Functo
46 type PullM t :: * -> *
46 type PullM t :: * -> *
47 -- | Merge a collection of events; the resulting Event will only occur if at least one input event is occuring, and will contain all of the input keys that are occurring simultaneously
47 -- | Merge a collection of events; the resulting Event will only occur if at least one input event is occuring, and will contain all of the input keys that are occurring simultaneously
48 merge :: GCompare k => DMap (WrapArg (Event t) k) -> Event t (DMap k) --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
48 merge :: GCompare k => DMap (WrapArg (Event t) k) -> Event t (DMap k) --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
49− -- | Efficiently fan-out an event to many destinations. This function should be partially applied, and then the result applied repeatedly to create child events
49+ -- | Efficiently fan-out an event to many destinations. This function should be partially applied, and then the result applied repeatedly to create child events
50 fan :: GCompare k => Event t (DMap k) -> EventSelector t k --TODO: Can we help enforce the partial application discipline here? The combinator is worthless without it
50 fan :: GCompare k => Event t (DMap k) -> EventSelector t k --TODO: Can we help enforce the partial application discipline here? The combinator is worthless without it
51 -- | Create an Event that will occur whenever the currently-selected input Event occurs
51 -- | Create an Event that will occur whenever the currently-selected input Event occurs
52 switch :: Behavior t (Event t a) -> Event t a
52 switch :: Behavior t (Event t a) -> Event t a
@@ -110,7 +110,7 @@ instance MonadHold t m => MonadHold t (ContT r m) where
110-- | Create an Event from another Event.
110-- | Create an Event from another Event.
111-- The provided function can sample 'Behavior's and hold 'Event's.
111-- The provided function can sample 'Behavior's and hold 'Event's.
112pushAlways :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
112pushAlways :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
113−pushAlways f e = push (liftM Just . f) e
113+pushAlways f = push (liftM Just . f)
115-- | Flipped version of 'fmap'.
115-- | Flipped version of 'fmap'.
116ffor :: Functor f => f a -> (a -> b) -> f b
116ffor :: Functor f => f a -> (a -> b) -> f b
@@ -298,7 +298,7 @@ dmapToThese m = case (DMap.lookup LeftTag m, DMap.lookup RightTag m) of
298-- 'Event's occurs. If both occur at the same time they are combined
298-- 'Event's occurs. If both occur at the same time they are combined
299-- using 'mappend'.
299-- using 'mappend'.
300appendEvents :: (Reflex t, Monoid a) => Event t a -> Event t a -> Event t a
300appendEvents :: (Reflex t, Monoid a) => Event t a -> Event t a -> Event t a
301−appendEvents e1 e2 = fmap (mergeThese mappend) $ align e1 e2
301+appendEvents e1 e2 = mergeThese mappend <$> align e1 e2
303{-# DEPRECATED sequenceThese "Use bisequenceA or bisequence from the bifunctors package instead" #-}
303{-# DEPRECATED sequenceThese "Use bisequenceA or bisequence from the bifunctors package instead" #-}
304sequenceThese :: Monad m => These (m a) (m b) -> m (These a b)
304sequenceThese :: Monad m => These (m a) (m b) -> m (These a b)
@@ -358,3 +358,9 @@ instance Reflex t => Align (Event t) where
358-- occurs and the 'Behavior' is true at the time of occurence.
358-- occurs and the 'Behavior' is true at the time of occurence.
359gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
359gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
360gate = attachWithMaybe $ \allow a -> if allow then Just a else Nothing
360gate = attachWithMaybe $ \allow a -> if allow then Just a else Nothing
362+-- | Create a new behavior given a starting behavior and switch to a the
363+-- behvior carried by the event when it fires.
364+switcher :: (Reflex t, MonadHold t m)
365+ => Behavior t a -> Event t (Behavior t a) -> m (Behavior t a)
366+switcher b eb = pull . (sample <=< sample) <$> hold b eb