module Control.Concurrent.Session.SMonad where
import Control.Monad.State
newtype SChain m x y a = SChain { runSChain :: x -> m (a, y) }
class SMonad (m :: * -> * -> * -> *) where
(~>>) :: m x y a -> m y z b -> m x z b
(~>>=) :: m x y a -> (a -> m y z b) -> m x z b
sreturn :: a -> m x x a
instance (Monad m) => SMonad (SChain m) where
f ~>> g = SChain $ \x -> do { (_, y) <- runSChain f x
; runSChain g y
}
f ~>>= g = SChain $ \x -> do { (a, y) <- runSChain f x
; runSChain (g a) y
}
sreturn a = SChain $ \x -> return (a, x)
instance (Monad m) => Monad (SChain m x x) where
m >> n = SChain $ \x -> do { ~(_, y) <- runSChain m x
; runSChain n y
}
m >>= k = SChain $ \x -> do { ~(a, y) <- runSChain m x
; runSChain (k a) y
}
return a = SChain $ \x -> return (a, x)
fail str = SChain $ \_ -> fail str
newtype SStateT s m x y a = SStateT { runSStateT :: s -> m x y (a, s) }
instance (SMonad m) => SMonad (SStateT s m) where
f ~>> g = SStateT $ \s -> runSStateT f s ~>>= \(_, s') ->
runSStateT g s'
f ~>>= g = SStateT $ \s -> runSStateT f s ~>>= \(a, s') ->
runSStateT (g a) s'
sreturn a = SStateT $ \s -> sreturn (a, s)
class SMonadTrans t where
slift :: (SMonad m) => m x y a -> t m x y a
instance SMonadTrans (SStateT s) where
slift f = SStateT $ \s -> f ~>>= \a -> sreturn (a, s)
class (SMonad m) => SMonadIO m where
sliftIO :: IO a -> m x x a
instance (MonadIO m) => SMonadIO (SChain m) where
sliftIO f = SChain $ \x -> do { a <- liftIO f
; return (a, x)
}
class (SMonad m) => SMonadState s m | m -> s where
sget :: m x x s
sput :: s -> m x x ()
instance (SMonad m) => SMonadState s (SStateT s m) where
sget = SStateT $ \s -> sreturn (s, s)
sput s = SStateT $ \_ -> sreturn ((), s)