
Andrea Rossato wrote:
Il Mon, Aug 28, 2006 at 09:28:02PM +0100, Brian Hulley ebbe a scrivere:
data Eval_SOI a = SOIE {runSOIE :: State -> (a, State, Output, Bool)}
well, I thought that this was not possible: (>>=) :: m a -> (a -> m b) -> m b
And you are right. In case of an exception, you don't have a 'b' to return, so you cannot construct the result (unless you put 'undefined' in there, which is just silly). Do it this way: data Eval_SOI a = SOIE {runSOIE :: State -> (Maybe a, State, Output)} instance Monad Eval_SOI where return a = SOIE $ \s -> (Just a, s, []) fail _ = SOIE $ \s -> (Nothing, s, []) m >>= k = SOIE $ \s0 -> let r@(ma, s1, o1) = runSOIE m s0 (mb, s2, o2) = runSOIE (k (fromJust ma)) s1 in case ma of Nothing -> r Just _ -> (mb, s2, o1 ++ o2) output w = SOIE $ \s -> (Just (), s, w) put s = SOIE $ \_ -> (Just (), s, []) get = SOIE $ \s -> (Just s, s, []) I don't think it's unmanageably complicated, but still not as clean and modular as using monad transformers.
This is why I think that two constructors are needed, but with two constructors is not possible...;-)
Indeed. Here they are Nothing and Just. In principle, Maybe is equivalent to a pair of a Bool and something else, but that only works in an untyped language.
I'm trying to dig into this problem also to see if it has to do with monad laws.
Uhh... no. You should prove them, though. (Try it, doing this is quite instructive.) Udo. -- "In the software business there are many enterprises for which it is not clear that science can help them; that science should try is not clear either." -- E. W. Dijkstra