[Haskell-beginners] Relation between monads and computations
byorgey at seas.upenn.edu
Tue Feb 14 18:16:21 CET 2012
On Thu, Feb 09, 2012 at 02:02:59PM +0300, Dmitriy Matrosov wrote:
> Hi, everyone!
> Not so long ago i started to learn haskell, and now i have a question
> about relation between monads and computations. In fact, i think, that
> i understand it and write some explanation for myself, but i'm not
> sure whether my explanation is correct or not, and will be very
> thankful if someone check it :) Here it is (i don't know category
> theory and my math knowledge is poor, so if i accidently use some
> terms from them incorrectly - it was just my understanding).
You say you have a question, but from reading the below I am not sure
what your question is...
Let me say first that while "monad" has a precise technical
definition, "computation" does not. So "the relation between monads
and computations" is not well-defined unless it is specified what you
mean by "computation". There are many ways to model different ideas
of "computation"; one of them is monads, but that is not the only way.
> Monads and computations.
> Generally computation consists of initial value, computation itself and the
> result. So it can be illustrated as:
> type a (M b) b
> data I ------> C <--------- E
> f ConstrM
> I :: a
> f :: a -> M b
> data M a = ContrM a | ...
> E :: b
> Let's see what happens: i take initial value I of type a and map it to some
> computation C (of type (M b)) using function f. Then, exist such value E of
> type b, that C = (ConstrM E). This value E will be the result of
That last part ("there exists a value E of type b ...") doesn't seem
right to me. There is no guarantee or requirement that a monad M be
defined so there is a constructor wrapping the "result". For example,
consider the list type:
data [a] =  | (a : [a])
In this case a function of type a -> [b] might produce a list
containing multiple values of type b. There is no single value of
type b which is the "result", and there is no constructor which wraps
a single value of type b into a list.
> Now consider two functions: unitM, which maps value into trivial computation
> (trivial computation is a computation, which result is equal to initial
> type a (M a) a
> data I ------> C <--------- I
> unitM ConstrM
> I :: a
> unitM :: a -> M a
> data M a = ContrM a | ...
> and bindM, which yields result from one computation, then applies some
> function f to the result, and makes another computation at the end (E is the
> result of this last computation).
> type (M a) a (M b) b
> data C ---------> I -------> C' <---------- E
> pattern f ConstrM
> data C --------------------> C' <---------- E
> C `bindM` f ConstrM
You have written this as if `bindM` works by extracting a single value
of type 'a' from C and running f on it, resulting in C'. But this is
not how it works. As I have shown above, there may not be a "single
value" that can be extracted from C. `bindM` works in a way that is
specific to M, and may involve running f multiple times, or not at
> Now, using fucntions unitM and bindM there is possibly to convert arbitrary
> function (k :: a -> b), which makes from initial value of type a value of type
> b, into terms of general computation (represented by type M).
Yes, (k :: a -> b) can be converted into a function of type (a -> M
b), but I think you have made it more complicated than necessary. All
you need to do is (unitM . k).
> type a (M a) a b (M b) b
> data I ------> C ---------> I ------> E -------> C' <-------- E
> unitM pattern k unitM ConstrM
> data I ------> C ---------> I -----------------> C' <-------- E
> unitM pattern f = (unitM . k) ConstrM
> data I ------> C ------------------------------> C' <-------- E
> unitM `bindM` f ConstrM
> data I --------------------------------------------> C' <-------- E
> g = (`bindM` f) . unitM ConstrM
(`bindM` f) . unitM is equivalent to just (unitM . k) by the monad laws.
> Monad is a way to implement such general computation, a way to write a program
> based on general computations, which later may be redefined, instead of
> particular ones, which redefinition leads to rewrite of large of amount of
> code. Monad is a triple of type constructor M and functions unitM and bindM
> (and errorM, probably?). Type constructor represents computation itself,
> functions unitM and bindM used to wrap your own specific computation (k :: a
> -> b) on types a and b into monadic notation (general computation
I think you have some of the right ideas, but some of the details seem
confused. (And no, the abstract idea of a monad does not include
errorM; the inclusion of 'fail' in the Monad class is just a hack
based on hsitorical accident.)
More information about the Beginners