> ...and report your findings here or blog somewhere if you don't mind
> :) I've been reading a lot about monads lately and can't get my head
> around it yet so any help appreciated (I'm coming from Java and
> Clojure is my first real functional language - that's why it causes
> headaches, I believe).
>


I have no blog so I will try an explanation here.
I think monad are quite difficult to grasp, so the more different
explanations you read, the better.
Monads are made to represent computations in an abstract way.
Sometimes the basic computation laws are not those you want
and then you want to introduce other computation laws.
Monad is one way to do so (among other like applicative functors or
Kieisli arrows)
Monad corresponds to the computations that are best described as an
imperative program.

So a monad is a type transformer: M<A> for all A , in Java words.
Something of type M<A> is a computation in the world of computation M
that returns values of type A.

(M for example can be
  IO: the computations that do input/outputs to find their results,
  State: the computations that use a and update an internal state
  List: more surprisingly, the non-deterministic computations: each
computation yeilds a list of possible results)

There are a few operators you need for a monad:
- return : A -> M<A> . It says that any computation model must be able
to handle the lack of computation. "Do nothing and return this value"
-  bind : M<A> -> (A -> M<B>) -> M<B>
"If I give you a computation that gives back values in A and for each
values in A I tell you how to compute a value in B,
 then you can compute a value in B. "
That's a strong assumption, because it allows to use the whole power
of Clojure to construct a computation from the result of the first
computation.
Some model of computations are more restrictive than monad on that.


>From this two operators you can define two others:
- map : (A -> B) -> M<A> -> M<B>
"If I give you a function from A to B, then you can transform a
computation that returns value in A in computation that returns values
in B."
(map f compA = (bind compA (fn [x] (return (f x)))))

- join : M<M<A>> -> M<A>
"I can run a subprogram" This is again something quite specific to
monad as computation devices. (Bind can be constructed from join and
map)
They are dynamic programs that can compute a program and run it.
join compMA = (bind compMA identity)

bind compA f = (join  (map f compA))

All these operators must respect some laws, that are quite natural.
Like returning a value and starting a computation is the same as starting a
computation directly from the value:

- (bind (return a) f) = (f a)

....

To work out an example, the state monad is a computation that can use
and modify a state, so: M<A> = S -> [S, A] . I need a state and return
a new state and a value A.
return a = (fn [s] -> [s a])
bind compA f =
  (fn [s1]  ->
    ; we give the state to the first comutation
   (let [[s2 a] (compA s1)
          ; we compute the next computation
         compB (f a)]
         ; we give the state to the second computation
         (compB s2)))

Hope that helps.

Nicolas.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to