That | m -> s reads "where m determines s", and means that there can be at most one s (here, the state type) for a given m (the monad type). This is used in type inference and checking to ensure that the type of state being carried around by a monad in MonadState is well defined, and to prevent you from having to annotate the operations in MonadState with type signatures. (To tell which type s to use.) Most monads have lots of ways out. IO is actually in my opinion, a fairly uncharacteristic example of a monad. With IO, the only IO operations given to you have IO occurring on the right hand side of the function arrow. With most types, this isn't the case. One of the best examples of a monad is the type constructor for lists, []. There, return x = [x], and x >>= f = concat (map f x). Now, once you have a value of type [a], there ought to be lots of ways to extract values of type 'a' from it, so long as you know what to do with the case that the list is empty (or can prove that it's not). Check out my article on the Haskell wiki for what I think is a very sensible way to look at monads (and the first way that I understood them myself): http://www.haskell.org/hawiki/MonadsAsContainers State computations of course, have evalState and execState, for putting an initial value into the state parameter, and collecting the resulting value, and the final state respectively. State computations are really just pure functions s -> (a,s), wrapped up in a type constructor, and with some special operations defined on them to chain them together, modify the state, copy it as the value, etc. In Haskell, every useful monad m basically has one of two things: either there's an operation m a -> a, or there's an operation m a -> IO a. This isn't entirely true, there might be other specific types which one might be interested in projecting to, but there must be some way to observe the resulting structure, or interpret it as a bunch of actions to run. This is because if there isn't, basically all that one can do is to stare at the resulting values in theoretical admiration -- they won't actually influence the program in any meaningful way. Anyway, have a look at my article and let me know what you think of it :) - Cale On 06/10/05, Tom Hawkins <tom@confluent.org> wrote:
I'm just starting to feel comfortable working inside IO; now I am trying to wrap my head around Control.Monad.State. Looking at the implementation, I came across some unfamiliar syntax...
class (Monad m) => MonadState s m | m -> s where
What is the meaning of "| m -> s"? I found no mention of it in the tutorial.
And slight logical dilemma...
With IO, I understand one your in it, you can't get out. I.e., any function that conducts IO must have IO _ in the type signature.
But this must not apply to all monads, otherwise the type signature for "main" would be rather messy (IO + State + every other monad used in a program). But I don't see how a monad could escape this fate since bind and return only produce more monads with the same type constructor.
Thanks for your help!
-Tom _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe