[Haskell-cafe] Re: [Haskell] State, StateT and lifting
Juan Carlos Arevalo Baeza
jcab.lists at JCABs-Rumblings.com
Sat Mar 19 06:25:32 EST 2005
Andrew Pimlott wrote:
>[I think it is preferred to post this on haskell-cafe.]
>
>
Oops! I guess you're right.
>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)
>
>
I don't know... The original using IO somehow offended me because it
was not an operation that required IO. This one leaves the inner monad
unspecified, but still looks like baggage to me.
>> 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).)
>
>
Yes, I did, thanx. I wrote the message a tad little bit too early :-P
>>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.
>
>
Yes. I prefer clarity, too. And I did it ugly (still groping with the
syntax). This is the final version:
liftState :: Monad m => State s a -> StateT s m a
liftState s = do
state1 <- get
let (result, state) = evalState (do {result <- s; state <- get;
return (result, state)}) state1
put state
return result
>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.
>
>
Cute, thanx! It's good to know I wasn't just missing something
obvious. So, this is my final implementation (works!):
state :: MonadState s m => (s -> (a, s)) -> m a
state sm = do
s <- get
let (result, newState) = sm s
put newState
return result
liftState :: Monad m => State s a -> StateT s m a
liftState (State f) = state f
JCAB
More information about the Haskell-Cafe
mailing list