{-# LANGUAGE BlockArguments, TupleSections #-} {-# OPTIONS_GHC -Wall -fno-warn-tabs #-} module Control.Monad.StateT (StateT(..), lift) where import Control.Applicative (Alternative(..)) import Control.Arrow (first) import Control.Monad (MonadPlus, (>=>)) --------------------------------------------------------------------------- -- * NEWTYPE STATE T -- * INSTANCE -- + FUNCTOR -- + APPLICATIVE AND ALTERNATIVE -- + MONAD AND MONAD PLUS --------------------------------------------------------------------------- -- NEWTYPE STATE T --------------------------------------------------------------------------- newtype StateT s m a = StateT { runStateT :: s -> m (a, s) } lift :: Functor m => m a -> StateT s m a lift m = StateT \s -> (, s) <$> m --------------------------------------------------------------------------- -- INSTANCE --------------------------------------------------------------------------- -- FUNCTOR instance Functor m => Functor (StateT s m) where f `fmap` StateT k = StateT $ ((f `first`) <$>) . k -- APPLICATIVE AND ALTERNATIVE instance Monad m => Applicative (StateT s m) where pure = StateT . (pure .) . (,) StateT kf <*> mx = StateT $ kf >=> \(f, s') -> (f <$> mx) `runStateT` s' instance MonadPlus m => Alternative (StateT s m) where empty = StateT $ const empty StateT k <|> StateT l = StateT $ (<|>) <$> k <*> l -- MONAD AND MONAD PLUS instance Monad m => Monad (StateT s m) where StateT k >>= f = StateT $ k >=> \(x, s') -> f x `runStateT` s' instance MonadPlus m => MonadPlus (StateT s m)