Just check this monad tutorial (attached). It's really great for beginners.
-- Andre
---BeginMessage---
-- Forwarded message --
Date: Tue, 05 Jun 2001 11:26:12 -0300
From: Andre Santos [EMAIL PROTECTED]
Newsgroups: depto.cursos.grad.if098
Subject: Monads for the Working Haskell Programmer
http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm
Title: Monads for the Working Haskell Programmer
Monads for the Working Haskell Programmer
-- a short tutorial.
Theodore Norvell
Memorial University of Newfoundland
New: Updated to Haskell '98.
This short tutorial introduces monads to Haskell programmers. It applies to Haskell
'98. Gofer programmers (are there any left?) can read it too; there is a section at the
end detailing the differences between Haskell and Gofer around monads and another about
the differences between Haskell 1.3, Haskell 1.4, and Haskell 98.
The reader is assumed to have a familiarity with the basics of Haskell programming such
as data declarations, function definitions, and lambda expressions. Familiarity with
classes and instance declarations will help.
Simulating states without Monads
Consider the following function
f1 w a = let (b, x) = g1 w a
(c, y) = h1 w x b
(d, z) = i1 w x y c
in (d, z)
where a, b, c, and d all have the same type, State.
In a sense this definition is very similar to an imperative program in which a
represents the initial state, d represents the final state, and b and c
represent intermediate states. The functions f1 w, g1 w, h1 w x,
and i1 w x y can be thought of as imperative routines that transform the state
and produce results. The results are like the return values in C programs and are bound to
variables x, y, and z in the example. A C routine that
corresponds to this would look something like this:
int f1(float w) {
const char x = g1(w) ;
const double y = h1(w, x) ;
const intz = i1(w, x, y) ;
return z ; }
All this explicit passing of states around can get a bit tedious, especially when
programs are modified. It also makes the program hard to read vs. the equivalent C
program.
Note that if we ignore the w, x, y, and z, then g1,
h1, and i1 are being composed. Can we define a kind of composition
operator that allows us to deal with the returned values as well as the state?
Simulating states with Monads
The functions that transform the state in the example above all have the type State
- (State, a) for some result type a. Let's generalize over the type of
the state and create a type to represent these transforms
type StateTrans s a = s - (s, a)
Let us define two functions. The first is a kind of composition function.
(=) :: StateTrans s a -
(a - StateTrans s b) -
StateTrans s b
p = k = \s0 - let (s1, a) = p s0
q = k a
in q s1
The second is a function that turns a value into an imperative program that
does not change the state, but returns the result.
return :: a - StateTrans s a
return a = \s - (s, a)
Our original function may now be written with all the shunting of state around hidden
by these operators:
f w = (g w) = (\x - (h w x) = (\y - (i w x y) = (\z - return z)))
You could also format this as follows
f w = g w = \x -
h w x = \y -
i w x y = \z -
return z
You should verify that f is equal to f1, if g = g1, h =
h1, and i = i1.
(Warning, if you really try to make the above definitions of = and return,
your Haskell compiler will complain, for reasons that will be explained later. However,
you could try changing the names a little, e.g. change = to ==
and change return to rtn.)
A nicer syntax
Now Haskell provides a nice syntax to sugar-coat the calls to =. It
turns out that the definition of f can also be written as
f w = do x - g w
y - h w x
z - i w x y
return z
The do is a keyword of Haskell. Any program involving a do can
be translated to one that doesn't use do by the following 4 rules:
1 An expression
do
pattern - expression
morelines
becomes expression = (\ pattern - do morelines)
2 An expression
do
expression
morelines
becomes expression do morelines
3 An expression
do
let declarationList
morelines
becomes
let
declarationList
in
do morelines
4. Finally when there is only one line in the do, an expression
do
expression
becomes expression
In the second rule, we saw the operator; this is used when the result of the
first operand is not subsequently used. It can always be defined as
p q = p = (\ _ - q)
So
do p
q
is the same as
do _ - p
q
The do notation follows the same conventions as other multi-line constructs
in Haskell. All lines must be vertically alligned. Alternatively, you may use braces and
semicolons if you prefer free format:
do {x - g w ;