{-# LANGUAGE CPP #-} -- | -- Copyright : (c) Ivan Perez and Manuel Baerenz, 2016 -- License : BSD3 -- Maintainer : ivan.perez@keera.co.uk -- -- 'MSF's with a 'State' monadic layer. -- -- This module contains functions to work with 'MSF's that include a 'State' -- monadic layer. This includes functions to create new 'MSF's that include an -- additional layer, and functions to flatten that layer out of the 'MSF`'s -- transformer stack. -- -- It is based on the _strict_ state monad 'Control.Monad.Trans.State.Strict', -- so when combining it with other modules such as @mtl@'s, -- the strict version has to be included, i.e. 'Control.Monad.State.Strict' -- instead of 'Control.Monad.State' or 'Control.Monad.State.Lazy'. module Control.Monad.Trans.MSF.State ( module Control.Monad.Trans.State.Strict -- * 'State' 'MSF' running and wrapping , stateS , runStateS , runStateS_ , runStateS__ ) where -- External imports #if !MIN_VERSION_base(4,8,0) import Control.Applicative ((<$>)) #endif import Control.Arrow (arr, (>>>)) import Control.Monad.Trans.State.Strict hiding (liftCallCC, liftCatch, liftListen, liftPass) import Data.Tuple (swap) -- Internal imports import Data.MonadicStreamFunction.Core (MSF, morphGS, feedback) -- * 'State' 'MSF' running and wrapping -- | Build an 'MSF' in the 'State' monad from one that takes the state as an -- extra input. This is the opposite of 'runStateS'. stateS :: (Functor m, Monad m) => MSF m (s, a) (s, b) -> MSF (StateT s m) a b stateS = morphGS $ \f a -> StateT $ \s -> (\((s', b), c) -> ((b, c), s')) <$> f (s, a) -- | Build an 'MSF' that takes a state as an extra input from one on the -- 'State' monad. This is the opposite of 'stateS'. runStateS :: (Functor m, Monad m) => MSF (StateT s m) a b -> MSF m (s, a) (s, b) runStateS = morphGS $ \f (s, a) -> (\((b, c), s') -> ((s', b), c)) <$> runStateT (f a) s -- | Build an 'MSF' /function/ that takes a fixed state as additional input, -- from an 'MSF' in the 'State' monad, and outputs the new state with every -- transformation step. runStateS_ :: (Functor m, Monad m) => MSF (StateT s m) a b -> s -> MSF m a (s, b) runStateS_ msf s = feedback s $ arr swap >>> runStateS msf >>> arr (\(s', b) -> ((s', b), s')) -- | Build an 'MSF' /function/ that takes a fixed state as additional input, -- from an 'MSF' in the 'State' monad. runStateS__ :: (Functor m, Monad m) => MSF (StateT s m) a b -> s -> MSF m a b runStateS__ msf s = runStateS_ msf s >>> arr snd