(Better view the below in a fixed-width font!) With all the recent monad discussions, I embarked on trying to clarify my own thoughts about them, and started to think about things in terms of just /where/ extra structure is 'understood'.
I think I can explain why 'a->IO b' is better than 'IO a->b'. The full title of this is really 'Explaining monads by comparison with comonads and arrows', but I didn't want to scare people off without putting in the above hook! We start with a simple single value of type 'a', and then we move into some other category, where the objects are 'thing a' instead, encapsulating some additional complexity - perhaps the possible absence or multiplicity of the value, perhaps extra state, opacity, etc. But whatever it is, the a-ness is still key for combing these objects. So lets look how they combine. Pay special attention to the f column. g f ??? g ??? f application a a->b flip ($) b monad bind m a a->m b >>= m b comonad cobind w a w a->b =>> w b arrow arr a b arr b c >>> arr a c simple application: f takes one argument, returns one result. monad: f still takes one argument, but now understands how to put things /into/ m. (Perhaps it just uses return::a->m a) comonad: f has access to the entire complexity of 'w a', understands how to get thing(s) out of it (coreturn), and distills it all down to one simple b. arrow: f has access to the entire complexity of the 'input' of arr b c, and does whatever is needed, to make the complexity of the 'output' of arr b c. Input/output may even be bidirectional! Also we can look at the job that ??? does. Remember that ??? has access to f as a function and can call it as many or as few times as it wishes. $: feeds a to f, once. >>=: picks zero or more a's from 'm a', feeds each one separately to f. opens up each of the 'm b' results to combine them into one 'm b'. =>>: feeds one or more versions of 'w a' to f, then builds a 'w b' in some way using the single b's (Perhaps inspired by 'w a') >>>: links g to f in some way, so they can interact in as complex a way as they like. Maybe it also contributes to that complexity. So now perhaps we can come to some conclusion about why monads are so useful and universal as control structures. It seems that monads are somehow the /simplest/ way of adding general control structure on top of single values. Notice how in a monad, the things that are combined together, the f's, still take just one 'a' argument. So theres no extra complexity for f in understanding its input. f can, however, put some additional complexity into its output - it can fail, or return multiple values, or whatever else is possible to encode in 'm a'. Still, f can be dumb, and just pass the problem onto some other function, maybe return. The complexity of the monad lives in one place, bind, >>=. It is bind that has the choice of calling f multiple times if it feels like it, and has the job of combining the results. bind is in control. f can only give it directions by returning one 'm b' for a given a. Contrast a comonad. Each f has to cope with an entire 'w a' on input. Moreover, it can't communicate any of that complexity back to cobind - it can only return one b. cobind only has the structure of 'w a' to inspire it in how to put together 'w b', it can receive /no/ instructions from f. Arrows are of course most general. Nothing is determined except that f talks with g in some way, and the compatibility is named 'b'. So given the choice of the above, which would /you/ choose, when the nature of the problem means one-on-one application is too simple? Surely a monad is the pick of the bunch! * f gives merely directions on control to >>= * f has to understand merely one single argument. (the monad can supply extra specialized functions like get/put, if we do want some complexity in there) * All the complex control structure is handled in one place - bind. And it has all the information available to do it well. Pity the poor comonad, only really suitable for infinite sequences! Shudder at the thought of the total complexity possible using arrows, and use them only when /really/ necessary. monad is king! -- [EMAIL PROTECTED]
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe