Hans van Thiel hthiel.char at zonnet.nl
Thu Sep 7 11:47:54 EDT 2006

```Hello All,

Being at the "Hello Monads" level, and having spent many hours on
understanding the following code from YAHT, maybe this will be helpful
to others.

{-cross ls1 ls2 = do
x <- ls1
y <- ls2
return (x,y)
-}

In the List Monad the value of cross is a list of pairs from the two
lists. Rewriting to:

{-cross ls1 ls2 = ls1 >>= \x ->
ls2 >>= \y ->
return (x, y)
-}

The actual function which gives an ordered pair is:

--hf1 = (\x y -> (x,y))

In the list Monad >>= is defined as the infix of bind, and return is the
same as make.

bind = flip concatMap
make x = [x]

So now cross can be written as:

--cross ls1 ls2 = ls1 `bind` (\x -> ls2 `bind` (\y -> make (x,y)))

With the prefix version of bind this becomes:

cross ls1 ls2 = bind ls1 (\x -> bind ls2 (\y -> make(x,y)))

Bind takes a list and a function. That function still looks complicated
(to me), because of the lambda abstraction, but the format is that the
second bind takes the list ls2 and another function, make, which has a
list of tuples as its value.

The point I want to make is, that the monadic computation is just
another function. The only difference is that the >== and return
functions have been defined centrally in the List Monad. Moreover, the
same notation has been defined in all other monads, but with different
meanings, appropriate to that monad. But you can use them. Cross ls1
ls2, for example, also works in the Maybe Monad, without any change at
all.

So the Monad class is, in essence, no different from the Num class (or
any other) where you also use predefined functions. These also will be
different for the different subordinate types.

Surely this is an oversimplification but, in for a dime, in for a
dollar:

An input procedure like getLine cannot be a function, because it will
return a different value each time it is called. Putting getLine inside
an IO Monad does not change this. What you can state, however, is that a
certain occurrence of getLine will return a certain value. So, if you
have a chain of IO actions, the first getLine will get this, the fifth
that, and so on. The value of these occurrences cannot change, simply
because they are uniquely identified.

But this is what the monadic sequence of actions achieves, it puts all
IO into a well defined chain where each action becomes unique, even
though names (like getLine) on the different positions are the same.
But again, the monadic computation is still a function.