{-# OPTIONS -fplugin=Rattus.Plugin #-} -- | Programming with many-shot events, i.e. events that may occur zero -- or more times. module Rattus.Event ( map , never , switch , switchTrans , Event , trigger , triggerMap ) where import Rattus import Rattus.Stream hiding (map) import qualified Rattus.Stream as Str import Prelude hiding (map) -- | Events are simply streams of 'Maybe''s. type Event a = Str (Maybe' a) -- all functions in this module are in Rattus {-# ANN module Rattus #-} -- | Apply a function to the values of the event (every time it occurs). {-# NOINLINE [1] map #-} map :: Box (a -> b) -> Event a -> Event b map :: Box (a -> b) -> Event a -> Event b map Box (a -> b) f (Just' a x ::: O (Event a) xs) = (b -> Maybe' b forall a. a -> Maybe' a Just' (Box (a -> b) -> a -> b forall a. Box a -> a unbox Box (a -> b) f a x)) Maybe' b -> O (Event b) -> Event b forall a. a -> O (Str a) -> Str a ::: Event b -> O (Event b) forall a. a -> O a delay (Box (a -> b) -> Event a -> Event b forall a b. Box (a -> b) -> Event a -> Event b map Box (a -> b) f (O (Event a) -> Event a forall a. O a -> a adv O (Event a) xs)) map Box (a -> b) f (Maybe' a Nothing' ::: O (Event a) xs) = Maybe' b forall a. Maybe' a Nothing' Maybe' b -> O (Event b) -> Event b forall a. a -> O (Str a) -> Str a ::: Event b -> O (Event b) forall a. a -> O a delay (Box (a -> b) -> Event a -> Event b forall a b. Box (a -> b) -> Event a -> Event b map Box (a -> b) f (O (Event a) -> Event a forall a. O a -> a adv O (Event a) xs)) -- | An event that will never occur. never :: Event a never :: Event a never = Maybe' a forall a. Maybe' a Nothing' Maybe' a -> O (Event a) -> Event a forall a. a -> O (Str a) -> Str a ::: Event a -> O (Event a) forall a. a -> O a delay Event a forall a. Event a never -- | @switch s e@ will behave like @s@ but switches to @s'$ every time -- the event 'e' occurs with some value @s'@. switch :: Str a -> Event (Str a) -> Str a switch :: Str a -> Event (Str a) -> Str a switch (a x ::: O (Str a) xs) (Maybe' (Str a) Nothing' ::: O (Event (Str a)) fas) = a x a -> O (Str a) -> Str a forall a. a -> O (Str a) -> Str a ::: Str a -> O (Str a) forall a. a -> O a delay (Str a -> Event (Str a) -> Str a forall a. Str a -> Event (Str a) -> Str a switch (O (Str a) -> Str a forall a. O a -> a adv O (Str a) xs) (O (Event (Str a)) -> Event (Str a) forall a. O a -> a adv O (Event (Str a)) fas)) switch Str a _xs (Just' (a a ::: O (Str a) as) ::: O (Event (Str a)) fas) = a a a -> O (Str a) -> Str a forall a. a -> O (Str a) -> Str a ::: ((Str a -> Event (Str a) -> Str a) -> O (Str a -> Event (Str a) -> Str a) forall a. a -> O a delay Str a -> Event (Str a) -> Str a forall a. Str a -> Event (Str a) -> Str a switch O (Str a -> Event (Str a) -> Str a) -> O (Str a) -> O (Event (Str a) -> Str a) forall a b. O (a -> b) -> O a -> O b <#> O (Str a) as O (Event (Str a) -> Str a) -> O (Event (Str a)) -> O (Str a) forall a b. O (a -> b) -> O a -> O b <#> O (Event (Str a)) fas) -- | Like 'switch' but works on stream functions instead of -- streams. That is, @switchTrans s e@ will behave like @s@ but -- switches to @s'$ every time the event 'e' occurs with some value -- @s'@. switchTrans :: (Str a -> Str b) -> Event (Str a -> Str b) -> (Str a -> Str b) switchTrans :: (Str a -> Str b) -> Event (Str a -> Str b) -> Str a -> Str b switchTrans Str a -> Str b f Event (Str a -> Str b) es Str a as = Str b -> Event (Str a -> Str b) -> Str a -> Str b forall b a. Str b -> Event (Str a -> Str b) -> Str a -> Str b switchTrans' (Str a -> Str b f Str a as) Event (Str a -> Str b) es Str a as -- | Helper function for 'switchTrans'. switchTrans' :: Str b -> Event (Str a -> Str b) -> Str a -> Str b switchTrans' :: Str b -> Event (Str a -> Str b) -> Str a -> Str b switchTrans' (b b ::: O (Str b) bs) (Maybe' (Str a -> Str b) Nothing' ::: O (Event (Str a -> Str b)) fs) (a _:::O (Str a) as) = b b b -> O (Str b) -> Str b forall a. a -> O (Str a) -> Str a ::: ((Str b -> Event (Str a -> Str b) -> Str a -> Str b) -> O (Str b -> Event (Str a -> Str b) -> Str a -> Str b) forall a. a -> O a delay Str b -> Event (Str a -> Str b) -> Str a -> Str b forall b a. Str b -> Event (Str a -> Str b) -> Str a -> Str b switchTrans' O (Str b -> Event (Str a -> Str b) -> Str a -> Str b) -> O (Str b) -> O (Event (Str a -> Str b) -> Str a -> Str b) forall a b. O (a -> b) -> O a -> O b <#> O (Str b) bs O (Event (Str a -> Str b) -> Str a -> Str b) -> O (Event (Str a -> Str b)) -> O (Str a -> Str b) forall a b. O (a -> b) -> O a -> O b <#> O (Event (Str a -> Str b)) fs O (Str a -> Str b) -> O (Str a) -> O (Str b) forall a b. O (a -> b) -> O a -> O b <#> O (Str a) as) switchTrans' Str b _xs (Just' Str a -> Str b f ::: O (Event (Str a -> Str b)) fs) as :: Str a as@(a _:::O (Str a) as') = b b' b -> O (Str b) -> Str b forall a. a -> O (Str a) -> Str a ::: ((Str b -> Event (Str a -> Str b) -> Str a -> Str b) -> O (Str b -> Event (Str a -> Str b) -> Str a -> Str b) forall a. a -> O a delay Str b -> Event (Str a -> Str b) -> Str a -> Str b forall b a. Str b -> Event (Str a -> Str b) -> Str a -> Str b switchTrans' O (Str b -> Event (Str a -> Str b) -> Str a -> Str b) -> O (Str b) -> O (Event (Str a -> Str b) -> Str a -> Str b) forall a b. O (a -> b) -> O a -> O b <#> O (Str b) bs' O (Event (Str a -> Str b) -> Str a -> Str b) -> O (Event (Str a -> Str b)) -> O (Str a -> Str b) forall a b. O (a -> b) -> O a -> O b <#> O (Event (Str a -> Str b)) fs O (Str a -> Str b) -> O (Str a) -> O (Str b) forall a b. O (a -> b) -> O a -> O b <#> O (Str a) as') where (b b' ::: O (Str b) bs') = Str a -> Str b f Str a as -- | Trigger an event as every time the given predicate turns true on -- the given stream. The value of the event is the same as that of the -- stream at that time. trigger :: Box (a -> Bool) -> Str a -> Event a trigger :: Box (a -> Bool) -> Str a -> Event a trigger Box (a -> Bool) p (a x ::: O (Str a) xs) = Maybe' a x' Maybe' a -> O (Event a) -> Event a forall a. a -> O (Str a) -> Str a ::: ((Str a -> Event a) -> O (Str a -> Event a) forall a. a -> O a delay (Box (a -> Bool) -> Str a -> Event a forall a. Box (a -> Bool) -> Str a -> Event a trigger Box (a -> Bool) p) O (Str a -> Event a) -> O (Str a) -> O (Event a) forall a b. O (a -> b) -> O a -> O b <#> O (Str a) xs) where x' :: Maybe' a x' = if Box (a -> Bool) -> a -> Bool forall a. Box a -> a unbox Box (a -> Bool) p a x then a -> Maybe' a forall a. a -> Maybe' a Just' a x else Maybe' a forall a. Maybe' a Nothing' -- | Trigger an event every time the given function produces a 'Just'' -- value. triggerMap :: Box (a -> Maybe' b) -> Str a -> Event b triggerMap :: Box (a -> Maybe' b) -> Str a -> Event b triggerMap = Box (a -> Maybe' b) -> Str a -> Event b forall a b. Box (a -> b) -> Str a -> Str b Str.map {-# RULES "map/map" forall f g xs. map f (map g xs) = map (box (unbox f . unbox g)) xs ; #-}