module Control.Observable (Observable, dispatch, subscribe, notify, obs) where import Control.Monad (forever) import Control.Monad.Trans.Cont (ContT (..)) import Control.Monad.Trans.Class (lift) newtype Mock r f a = Mock { mock :: f r } -- | Mock used here as delimiter type Observable f a r = ContT r (Mock r f) a -- | Make continuation to be observable dispatch :: ContT r f a -> Observable f a r dispatch f = ContT $ \h -> Mock $ runContT f (mock . h) -- | Make monadic action to be observable obs :: Monad f => f a -> Observable f a r obs action = dispatch (lift action) -- | Listen all event from action, forever subscribe :: Applicative f => Observable f a r -> (a -> f r) -> f r subscribe r f = forever $ mock $ runContT r (Mock . f) -- | Listen only first event, just once notify :: Observable f a r -> (a -> f r) -> f r notify r f = mock $ runContT r (Mock . f)