X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=week7.mdwn;h=7544425c4bbcca2c3a1b72cf0cf088199a18586f;hp=4c74015b9a3f94bef3a5497f8cfaed25d779014a;hb=fff7086c5dec8448c3a5369f3df88b50ffd06e6b;hpb=1c06c5dab40e8cc8bb1bf89bfe65a7d6741d3cbf
diff --git a/week7.mdwn b/week7.mdwn
index 4c74015b..7544425c 100644
--- a/week7.mdwn
+++ b/week7.mdwn
@@ -402,11 +402,16 @@ them from hurting the people that use them or themselves.
* **Associativity: bind obeys a kind of associativity**. Like this:
- (u >>= f) >>= g == u >>= (fun x -> f x >>= g)
+ (u >>= f) >>= g == u >>= (fun x -> f x >>= g)
If you don't understand why the lambda form is necessary (the
"fun x -> ..." part), you need to look again at the type of `bind`.
+ Wadler and others try to make this look nicer by phrasing it like this,
+ where U, V, and W are schematic for any expressions with the relevant monadic type:
+
+ (U >>= fun x -> V) >>= fun y -> W == U >>= fun x -> (V >>= fun y -> W)
+
Some examples of associativity in the Option monad (bear in
mind that in the Ocaml implementation of integer division, 2/3
evaluates to zero, throwing away the remainder):
@@ -426,15 +431,15 @@ them from hurting the people that use them or themselves.
# Some 3 >>= (fun x -> divide 2 x >>= divide 6);;
- : int option = None
-Of course, associativity must hold for *arbitrary* functions of
-type `'a -> 'b m`, where `m` is the monad type. It's easy to
-convince yourself that the `bind` operation for the Option monad
-obeys associativity by dividing the inputs into cases: if `u`
-matches `None`, both computations will result in `None`; if
-`u` matches `Some x`, and `f x` evalutes to `None`, then both
-computations will again result in `None`; and if the value of
-`f x` matches `Some y`, then both computations will evaluate
-to `g y`.
+ Of course, associativity must hold for *arbitrary* functions of
+ type `'a -> 'b m`, where `m` is the monad type. It's easy to
+ convince yourself that the `bind` operation for the Option monad
+ obeys associativity by dividing the inputs into cases: if `u`
+ matches `None`, both computations will result in `None`; if
+ `u` matches `Some x`, and `f x` evalutes to `None`, then both
+ computations will again result in `None`; and if the value of
+ `f x` matches `Some y`, then both computations will evaluate
+ to `g y`.
* **Right identity: unit is a right identity for bind.** That is,
`u >>= unit == u` for all monad objects `u`. For instance,
@@ -462,6 +467,7 @@ Theory](/advanced_topics/monads_in_category_theory).
See also:
* [Haskell wikibook on Monad Laws](http://www.haskell.org/haskellwiki/Monad_Laws).
+* [Yet Another Haskell Tutorial on Monad Laws](http://en.wikibooks.org/wiki/Haskell/YAHT/Monads#Definition)
* [Haskell wikibook on Understanding Monads](http://en.wikibooks.org/wiki/Haskell/Understanding_monads)
* [Haskell wikibook on Advanced Monads](http://en.wikibooks.org/wiki/Haskell/Advanced_monads)
* [Haskell wikibook on do-notation](http://en.wikibooks.org/wiki/Haskell/do_Notation)