{-# LANGUAGE RecursiveDo #-}
module Event where
import Control.Applicative
import Control.Monad
import Control.Monad.Fix
import Data.Maybe
import FRP.Elerea.Experimental
import Util
{-| Events are signals with an option type. -}
type Event p a = Signal p (Maybe a)
{-| Sample a signal whenever a changing condition is true. -}
ifE :: Signal p Bool -> Signal p a -> Event p a
ifE c s = c >>= \b -> if b then Just <$> s else return Nothing
{-| Left-biased merge. -}
leftE :: Event p a -> Event p a -> Event p a
leftE e1 e2 = e1 >>= maybeE e2
{-| Right-biased merge. -}
rightE :: Event p a -> Event p a -> Event p a
rightE e1 e2 = e2 >>= maybeE e1
{-| Left-biased merge of several events. -}
mergeE :: [Event p a] -> Event p a
mergeE [] = return Nothing
mergeE (e:es) = e >>= maybeE (mergeE es)
{-| Maintain a changing list of entities fed in as events along with a
function to derive the corresponding signal of the removal condition
(the signal is removed when the associated removal signal is 'True' for
the first time). -}
collectE :: Event p a -> (a -> Signal p Bool) -> SignalGen p (Signal p [a])
collectE e f = mdo
col <- delay [] col'
col' <- dmemo [] $ filterM (fmap not . f) =<< liftM2 ((++).maybeToList) e col
return col'
{-| A helper function equivalent to @flip maybe (return.Just)@. -}
maybeE :: Event p a -> Maybe a -> Event p a
maybeE e Nothing = e
maybeE _ jx = return jx