{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.StateT (
StateT(..)
, runStateT
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans.Class
newtype StateT
(mark :: * -> *)
(s :: *)
(m :: * -> *)
(a :: *)
= StateT
{ unStateT :: s -> m (Pair s a)
} deriving (Typeable)
instance
( Typeable s, Typeable m, Typeable a, Typeable mark
) => Show (StateT mark s m a)
where
show
:: StateT mark s m a
-> String
show = show . typeOf
instance
( Monad m, MonadIdentity mark
) => Functor (StateT mark s m)
where
fmap
:: (a -> b)
-> StateT mark s m a
-> StateT mark s m b
fmap f (StateT x) =
StateT $ \s1 -> do
Pair s2 a <- x s1
return $ Pair s2 (f a)
instance
( Monad m, MonadIdentity mark
) => Applicative (StateT mark s m)
where
pure
:: a
-> StateT mark s m a
pure x =
StateT $ \s -> pure $ Pair s x
(<*>)
:: StateT mark s m (a -> b)
-> StateT mark s m a
-> StateT mark s m b
(StateT f) <*> (StateT x) =
StateT $ \s1 -> do
Pair s2 g <- f s1
Pair s3 a <- x s2
return $ Pair s3 (g a)
instance
( Monad m, MonadIdentity mark
) => Monad (StateT mark s m)
where
return
:: a
-> StateT mark s m a
return x =
StateT $ \s -> return $ Pair s x
(>>=)
:: StateT mark s m a
-> (a -> StateT mark s m b)
-> StateT mark s m b
(StateT x) >>= f =
StateT $ \s1 -> do
Pair s2 a <- x s1
unStateT (f a) s2
instance
( MonadIdentity mark
) => MonadTrans (StateT mark s)
where
lift
:: ( Monad m )
=> m a
-> StateT mark s m a
lift x = StateT $ \s -> fmap (\a -> Pair s a) x
instance
( MonadIdentity mark
) => MonadFunctor (StateT mark s)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> StateT mark s m a
-> StateT mark s n a
hoist f (StateT x) =
StateT $ \s -> do
a <- f $ fmap slot2 (x s)
return $ Pair s a
instance
( EqIn m, MonadIdentity mark, Eq s
) => EqIn (StateT mark s m)
where
newtype Context (StateT mark s m)
= StateTCtx
{ unStateTCtx :: (mark s, Context m)
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (StateT mark s m)
-> StateT mark s m a
-> StateT mark s m a
-> Bool
eqIn (StateTCtx (s,h)) (StateT x) (StateT y) =
eqIn h (x $ unwrap s) (y $ unwrap s)
deriving instance
( Eq (mark s), Eq (Context m)
) => Eq (Context (StateT mark s m))
deriving instance
( Show (mark s), Show (Context m)
) => Show (Context (StateT mark s m))
instance
( MonadIdentity mark
) => RunMonadTrans (StateT mark s)
where
newtype InputT (StateT mark s)
= StateTIn
{ unStateTIn :: mark s
} deriving (Typeable)
newtype OutputT (StateT mark s) a
= StateTOut
{ unStateTOut :: Pair (mark s) a
} deriving (Typeable)
runT
:: ( Monad m )
=> InputT (StateT mark s)
-> StateT mark s m a
-> m (OutputT (StateT mark s) a)
runT (StateTIn s) (StateT x) = do
Pair s1 a <- x (unwrap s)
return $ StateTOut $ Pair (pure s1) a
runStateT
:: ( Monad m, MonadIdentity mark )
=> mark s
-> StateT mark s m a
-> m (Pair (mark s) a)
runStateT inp =
fmap unStateTOut . runT (StateTIn inp)
deriving instance
( Eq (mark s)
) => Eq (InputT (StateT mark s))
deriving instance
( Show (mark s)
) => Show (InputT (StateT mark s))
deriving instance
( Eq (mark s), Eq a
) => Eq (OutputT (StateT mark s) a)
deriving instance
( Show (mark s), Show a
) => Show (OutputT (StateT mark s) a)
instance
( MonadIdentity mark
) => LiftCatch (StateT mark s)
where
liftCatch
:: ( Monad m )
=> Catch e m (OutputT (StateT mark s) a)
-> Catch e (StateT mark s m) a
liftCatch catch x h = StateT $ \s ->
fmap (bimap1 unwrap . unStateTOut) $ catch
(fmap (StateTOut . bimap1 pure) $ unStateT x s)
(\e -> fmap (StateTOut . bimap1 pure) $ unStateT (h e) s)
instance
( MonadIdentity mark
) => LiftDraft (StateT mark s)
where
liftDraft
:: ( Monad m )
=> Draft w m (OutputT (StateT mark s) a)
-> Draft w (StateT mark s m) a
liftDraft draft x =
StateT $ \s -> do
Pair w (StateTOut (Pair s a)) <- draft $ fmap (StateTOut . bimap1 pure) $ unStateT x s
return $ Pair (unwrap s) (Pair w a)
instance
( MonadIdentity mark
) => LiftLocal (StateT mark s)
where
liftLocal
:: ( Monad m )
=> Local r m (OutputT (StateT mark s) a)
-> Local r (StateT mark s m) a
liftLocal local f x =
StateT $ \s -> do
StateTOut (Pair s1 a) <- local f $ fmap (StateTOut . bimap1 pure) $ unStateT x s
return $ Pair (unwrap s1) a
instance {-# OVERLAPPING #-}
( Monad m, MonadIdentity mark
) => MonadState mark s (StateT mark s m)
where
get
:: StateT mark s m (mark s)
get = StateT $ \s -> return (Pair s (pure s))
put
:: mark s
-> StateT mark s m ()
put s = StateT $ \_ -> return (Pair (unwrap s) ())
instance {-# OVERLAPPABLE #-}
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadState mark s m
) => MonadState mark s (StateT mark1 s1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadReadOnly mark r m
) => MonadReadOnly mark r (StateT mark1 s m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnly mark w m, Monoid w
) => MonadWriteOnly mark w (StateT mark1 s m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadExcept mark e m
) => MonadExcept mark e (StateT mark1 s m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadPrompt mark p m
) => MonadPrompt mark p (StateT mark1 s m)
instance
( Monad m, MonadIdentity mark1, MonadIdentity mark
, MonadHalt mark m
) => MonadHalt mark (StateT mark1 s m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadAppendOnly mark w m, Monoid w
) => MonadAppendOnly mark w (StateT mark1 s m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnce mark w m
) => MonadWriteOnce mark w (StateT mark1 s m)