module Control.Effects (
with
, run
, Handler(..)
, operation
, runBase
, base
, Layer
, Base
, Pure
, Effect
, AutoLift
, AutoLiftBase
) where
import Control.Applicative
with :: Monad m => Handler e r m a -> (Effect e m -> Layer e m a) -> m r
with h f = runLayer (f Effect) (ret h) >>= fin h
run :: Base Pure a -> a
run (Base (Pure a)) = a
data Handler e r m a = Handler
{ ret :: a -> m e
, fin :: e -> m r
}
operation :: AutoLift e m n => Effect e m -> ((a -> m e) -> m e) -> n a
operation = operation'
base :: AutoLiftBase m n => m a -> n a
base = base'
runBase :: Base m a -> m a
runBase (Base m) = m
newtype Layer e m a = Layer { runLayer :: (a -> m e) -> m e }
instance Functor (Layer r m) where
fmap f m = Layer $ \k -> runLayer m (k . f)
instance Applicative (Layer r m) where
pure a = Layer $ \k -> k a
m <*> v = Layer $ \k -> runLayer m (\f -> runLayer v (k . f))
instance Monad (Layer e m) where
return a = Layer $ \k -> k a
m >>= f = Layer $ \k -> runLayer m (\a -> runLayer (f a) k)
newtype Pure a = Pure a
instance Functor Pure where
fmap f (Pure a) = Pure (f a)
instance Applicative Pure where
pure = Pure
Pure f <*> Pure a = Pure (f a)
instance Monad Pure where
return = Pure
Pure a >>= f = f a
newtype Base m a = Base (m a)
instance Functor m => Functor (Base m) where
fmap f (Base m) = Base (fmap f m)
instance Applicative m => Applicative (Base m) where
pure = Base . pure
Base m <*> Base v = Base (m <*> v)
instance Monad m => Monad (Base m) where
return = Base . return
Base m >>= f = Base $ m >>= runBase . f
data Effect e (m :: * -> *) = Effect
class (Monad m, Monad n) => AutoLift e m n where
operation' :: Effect e m -> ((a -> m e) -> m e) -> n a
instance (Monad m, Monad n, AutoLiftInternal (Layer e m) (Base n) (Layer e m) (Base n)) => AutoLift e m (Base n) where
operation' _ f = autolift (Proxy :: Proxy (Layer e m)) (Proxy :: Proxy (Base n)) (Layer f)
instance (Monad m, Monad n, AutoLiftInternal (Layer e m) (Layer d n) (Layer e m) (Layer d n)) => AutoLift e m (Layer d n) where
operation' _ f = autolift (Proxy :: Proxy (Layer e m)) (Proxy :: Proxy (Layer d n)) (Layer f)
class (Monad m, Monad n) => AutoLiftBase m n where
base' :: m a -> n a
instance (Monad m, Monad n, AutoLiftInternal (Base m) (Base n) (Base m) (Base n)) => AutoLiftBase m (Base n) where
base' m = autolift (Proxy :: Proxy (Base m)) (Proxy :: Proxy (Base n)) (Base m)
instance (Monad m, Monad n, AutoLiftInternal (Base m) (Layer e n) (Base m) (Layer e n)) => AutoLiftBase m (Layer e n) where
base' m = autolift (Proxy :: Proxy (Base m)) (Proxy :: Proxy (Layer e n)) (Base m)
data Proxy (m :: * -> *) = Proxy
class (Monad m1, Monad m2) => AutoLiftInternal m1 m2 n1 n2 where
autolift :: Proxy n1 -> Proxy n2 -> m1 a -> m2 a
pre :: Proxy (Layer r m) -> Proxy m
pre Proxy = Proxy
instance (Monad m) => AutoLiftInternal m m (Base n) (Base n) where
autolift Proxy Proxy = id
instance (AutoLiftInternal m1 m2 (Base n1) n2) => AutoLiftInternal m1 (Layer r m2) (Base n1) (Layer s n2) where
autolift p1 p2 = Layer . (>>=) . autolift p1 (pre p2)
instance (AutoLiftInternal m1 m2 n1 n2) => AutoLiftInternal m1 m2 (Layer r n1) (Layer s n2) where
autolift p1 p2 = autolift (pre p1) (pre p2)