module Control.Observable (Observable, (*=>), dispatch, subscribe, notify, obs, bypass) where
import "base" Control.Applicative (Applicative (pure))
import "base" Control.Monad (Monad, forever)
import "base" Data.Function (($), (.), flip)
import "base" Data.Traversable (Traversable (traverse))
import "transformers" Control.Monad.Trans.Cont (ContT (..))
import "transformers" Control.Monad.Trans.Class (lift)
newtype Capture r f a = Capture { captured :: f r }
type Observable f a r = ContT r (Capture r f) a
dispatch :: ContT r f a -> Observable f a r
dispatch f = ContT $ \h -> Capture $ runContT f (captured . h)
obs :: Monad f => f a -> Observable f a r
obs action = dispatch $ lift action
subscribe :: Applicative f => Observable f a r -> (a -> f r) -> f r
subscribe r f = forever $ captured $ runContT r (Capture . f)
notify :: Observable f a r -> (a -> f r) -> f r
notify r f = captured $ runContT r (Capture . f)
(*=>) :: Monad f => f a -> (a -> f r) -> f r
action *=> handler = subscribe (obs action) handler
bypass :: (Monad f, Traversable t) => t a -> (a -> f r) -> f (t r)
bypass xs h = traverse (flip notify h . dispatch . pure) xs