When I was studying Monad Transformer, I decided to create StateT s m a
from scratch with instances for Functor
, Applicative
and Monad
.
This is what I have:
newtype StateT s m a = StateT { runStateT :: (s -> m (a, s)) }
instance Functor m => Functor (StateT s m) where
-- fmap :: (a -> b) -> StateT s m a -> StateT s m b
-- which is (a -> b) -> (s -> m (a, s)) -> (s -> m (b, s))
f `fmap` (StateT x) = StateT $ \ s -> fmap run (x s)
where run (a, s) = (f a, s)
instance Monad m => Applicative (StateT s m) where
-- pure :: a -> StateT s m a
pure a = StateT $ \ s -> pure (a, s)
-- <*> :: f (a -> b) -> f a -> f b
-- which is StateT s m (a -> b) -> StateT s m a -> State s m b
k <*> x = StateT $ \ s -> do
(f, s1) <- runStateT k s -- :: m ((a -> b), s)
(a, s2) <- runStateT x s1
return (f a, s2)
instance (Monad m) => Monad (StateT s m) where
return a = StateT $ \ s -> return (a, s)
-- >>= :: StateT s m a -> (a -> StateT s m b) -> StateT s m b
(StateT x) >>= f = StateT $ \ s -> do
(v, s') <- x s
runStateT (f v) s'
My original intention is to implement Functor (StateT s m)
with Functor m
restriction, Applicative (StateT s m)
with Applicative m
restriction, and Monad (StateT s m) with
Monad m) restriction. However I couldn't do the Applicative
case and had to use Monad m
restriction instead. Is there a way to do it with Applicative m
?
Thank you in advance.