packages feed

parsley-core-2.1.0.1: src/ghc/Parsley/Internal/Common/State.hs

{-# LANGUAGE DeriveFunctor,
             MultiParamTypeClasses,
             DerivingStrategies,
             CPP #-}
module Parsley.Internal.Common.State (
    State, StateT,
    runState, evalState, execState,
    runStateT, evalStateT, execStateT,
    module Control.Monad.State.Class
  ) where

import Control.Applicative       (liftA2, Alternative(..))
#if __GLASGOW_HASKELL__ < 808
import Control.Monad.Fail        (MonadFail(..))
#endif
import Control.Monad.Fix         (MonadFix(..))
import Control.Monad.Identity    (Identity, runIdentity)
import Control.Monad.State.Class
import Control.Monad.Trans       (MonadTrans(..), MonadIO(..))

#if __GLASGOW_HASKELL__ < 808
import qualified Control.Monad.Fail as Fail (MonadFail(fail))
#endif

type State s = StateT s Identity
{-# INLINE runState #-}
runState :: State s a -> s -> (a, s)
runState mx = runIdentity . runStateT mx

{-# INLINE evalState #-}
evalState :: State s a -> s -> a
evalState mx = runIdentity . evalStateT mx

{-# INLINE execState #-}
execState :: State s a -> s -> s
execState mx = runIdentity . execStateT mx

newtype StateT s m a = StateT {unStateT :: forall r. s -> (a -> s -> m r) -> m r} deriving stock Functor

{-# INLINE runStateT #-}
runStateT :: Monad m => StateT s m a -> s -> m (a, s)
runStateT (StateT f) s = f s (curry return)

{-# INLINE evalStateT #-}
evalStateT :: Monad m => StateT s m a -> s -> m a
evalStateT (StateT f) s = f s (const . return)

{-# INLINE execStateT #-}
execStateT :: Monad m => StateT s m a -> s -> m s
execStateT (StateT f) s = f s (const return)

instance Applicative (StateT s m) where
  {-# INLINE pure #-}
  pure x = StateT (flip ($ x))
  {-# INLINE liftA2 #-}
  liftA2 f (StateT mx) (StateT my) = StateT (\s k -> mx s (\x s' -> my s' (k . f x)))

instance Monad (StateT s m) where
  {-# INLINE return #-}
  return = pure
  {-# INLINE (>>=) #-}
  StateT mx >>= f = StateT (\s k -> mx s (\x s' -> unStateT (f x) s' k))

instance MonadFix m => MonadFix (StateT s m) where
  {-# INLINE mfix #-}
  mfix f = StateT (\s k -> mfix (\ ~(x, _) -> runStateT (f x) s) >>= uncurry k)

instance MonadTrans (StateT s) where
  {-# INLINE lift #-}
  lift m = StateT (\s k -> m >>= (`k` s))

instance MonadIO m => MonadIO (StateT s m) where liftIO = lift . liftIO

instance MonadFail m => MonadFail (StateT s m) where
#if __GLASGOW_HASKELL__ < 808
  fail msg = StateT (\_ _ -> Fail.fail msg)
#else
  fail msg = StateT (\_ _ -> fail msg)
#endif

instance Alternative m => Alternative (StateT s m) where
  empty = StateT (\_ _ -> empty)
  StateT mx <|> StateT my = StateT (\s k -> mx s k <|> my s k)

instance MonadState s (StateT s m) where
  get = StateT (\s k -> k s s)
  put s = StateT (\_ k -> k () s)