[Haskell] State, StateT and lifting
Andrew Pimlott
andrew at pimlott.net
Fri Mar 18 19:09:50 EST 2005
[I think it is preferred to post this on haskell-cafe.]
On Fri, Mar 18, 2005 at 02:00:37PM -0800, Juan Carlos Arevalo Baeza wrote:
> matchRuleST :: String -> State RuleSet (Maybe Rule)
> makeST :: String -> StateT RuleSet IO ()
>
> matchRuleST doesn't really need IO for anything (it just works on the
> current state "RuleSet"). makeST needs IO (it does file date
> comparisons, actions on the files, etc... the usual "make" stuff). The
> problem is how to properly use matchRuleST from makeST.
You might solve this by changing the type of matchRuleST:
matchRuleST :: MonadState RuleSet m => String -> m (maybe Rule)
(This requires -fglasgow-exts, but I don't think there's anything
controversial about non-variables in class constraints.)
> Then, I decided to try again, and came up with this function:
>
> liftState :: State s a -> StateT s m a
(I think you left out the constraint (Monad m).)
> liftState s = do
> state1 <- get
> (
> let (result, state) = evalState (do {result <- s; state <- get;
> return (result, state)}) state1 in do
> put state
> return result
> )
You can turn this into a one-liner if you work on it a bit. But I would
go with the above.
Aside: It bugs me that this is not defined by Control.Monad.State
(alongside modify and gets):
state :: MonadState s m => (s -> (a, s)) -> m a
I almost always end up defining it myself and use it to implement other
state transformers. I would do the same for other monad classes
(Writer, etc): provide a function that captures the general operation.
Andrew
More information about the Haskell
mailing list