{-# OPTIONS -fplugin=Rattus.Plugin #-}
{-# LANGUAGE TypeOperators #-}
module Rattus.Event
( map
, never
, switch
, switchTrans
, whenJust
, Event(..)
, await
, trigger
, triggerMap
)
where
import Rattus
import Rattus.Stream hiding (map)
import Prelude hiding ((<*>), map)
data Event a = Now !a | Wait !(O (Event a))
{-# ANN module Rattus #-}
{-# NOINLINE [1] map #-}
map :: Box (a -> b) -> Event a -> Event b
map f (Now x) = Now (unbox f x)
map f (Wait x) = Wait (delay (map f) <*> x)
never :: Event a
never = Wait (delay never)
switch :: Str a -> Event (Str a) -> Str a
switch (x ::: xs) (Wait fas) = x ::: (delay switch <*> xs <*> fas)
switch _xs (Now ys) = ys
firstJust :: Str (Maybe' a) -> Event a
firstJust (Just' x ::: _) = Now x
firstJust (Nothing' ::: xs) = Wait (delay firstJust <*> xs)
whenJust :: Str (Maybe' a) -> Str (Event a)
whenJust cur@(_ ::: xs) = firstJust cur ::: (delay whenJust <*> xs)
switchTrans :: (Str a -> Str b) -> Event (Str a -> Str b) -> (Str a -> Str b)
switchTrans f es as = switchTrans' (f as) es as
switchTrans' :: Str b -> Event (Str a -> Str b) -> Str a -> Str b
switchTrans' (x ::: xs) (Wait fas) (_:::is) = x ::: (delay switchTrans' <*> xs <*> fas <*> is)
switchTrans' _xs (Now ys) is = ys is
await1 :: Stable a => a -> Event b -> Event (a :* b)
await1 a (Wait eb) = Wait (delay await1 <** a <*> eb)
await1 a (Now b) = Now (a :* b)
await2 :: Stable b => b -> Event a -> Event (a :* b)
await2 b (Wait ea) = Wait (delay await2 <** b <*> ea)
await2 b (Now a) = Now (a :* b)
await :: (Stable a, Stable b) => Event a -> Event b -> Event(a :* b)
await (Wait ea) (Wait eb) = Wait (delay await <*> ea <*> eb)
await (Now a) eb = await1 a eb
await ea (Now b) = await2 b ea
trigger :: Box (a -> Bool) -> Str a -> Event a
trigger p (x ::: xs)
| unbox p x = Now x
| otherwise = Wait (delay (trigger p) <*> xs)
triggerMap :: Box (a -> Maybe' b) -> Str a -> Event b
triggerMap f (x ::: xs) =
case unbox f x of
Just' y -> Now y
Nothing' -> Wait (delay (triggerMap f) <*> xs)
{-# RULES
"map/map" forall f g xs.
map f (map g xs) = map (box (unbox f . unbox g)) xs ;
#-}