-- | Phantom Monad State Transformer constructor and functions. module Control.Monad.PhantomState ( PhantomStateT (..) , PhantomState , useState , changeState , runPhantomStateT , runPhantomState ) where import Control.Applicative import Control.Monad.Trans.Class import Data.Functor.Identity -- | The Phantom State Monad Transformer is like the -- State Monad Transformer, but it does not hold -- any value. newtype PhantomStateT s m a = PhantomStateT (s -> m s) -- | Type synonym of 'PhantomStateT' where the underlying 'Monad' is the 'Identity' monad. type PhantomState s a = PhantomStateT s Identity a -- | Perform an applicative action using the current state, leaving -- the state unchanged. useState :: Applicative m => (s -> m a) -> PhantomStateT s m () {-# INLINE useState #-} useState f = PhantomStateT $ \x -> f x *> pure x -- | Modify the state using a pure function. changeState :: Applicative m => (s -> s) -> PhantomStateT s m () {-# INLINE changeState #-} changeState f = PhantomStateT $ pure . f -- | Perform a phantom state computation by setting an initial state -- and running all the actions from there. runPhantomStateT :: PhantomStateT s m a -- ^ Phantom state computation -> s -- ^ Initial state -> m s -- ^ Final result {-# INLINE runPhantomStateT #-} runPhantomStateT (PhantomStateT f) x = f x -- | Specialized version of 'runPhantomStateT' where the underlying -- 'Monad' is the 'Identity' monad. runPhantomState :: PhantomState s a -- ^ Phantom state computation -> s -- ^ Initial state -> s -- ^ Final result {-# INLINE runPhantomState #-} runPhantomState f = runIdentity . runPhantomStateT f -- Instances instance Functor (PhantomStateT s m) where {-# INLINE fmap #-} fmap _ (PhantomStateT f) = PhantomStateT f instance Monad m => Applicative (PhantomStateT s m) where {-# INLINE pure #-} pure _ = PhantomStateT return {-# INLINE (<*>) #-} PhantomStateT f <*> PhantomStateT g = PhantomStateT (\x -> f x >>= g) {-# INLINE (*>) #-} PhantomStateT f *> PhantomStateT g = PhantomStateT (\x -> f x >>= g) {-# INLINE (<*) #-} PhantomStateT f <* PhantomStateT g = PhantomStateT (\x -> f x >>= g) instance Monad m => Monad (PhantomStateT s m) where {-# INLINE return #-} return = pure {-# INLINE (>>=) #-} x >>= f = x *> f undefined {-# INLINE (>>) #-} (>>) = (*>) instance MonadTrans (PhantomStateT s) where {-# INLINE lift #-} lift m = PhantomStateT (\x -> m >> return x)