
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