author Chris Barker Mon, 1 Nov 2010 14:25:19 +0000 (10:25 -0400) committer Chris Barker Mon, 1 Nov 2010 14:25:19 +0000 (10:25 -0400)
 week7.mdwn patch | blob | history

index e4e884b..8daff8a 100644 (file)
@@ -310,8 +310,8 @@ homework may recognize this last expression.  You can think of the
notation like this: take the singing box `u` and evaluate it (which
includes listening to the song).  Take the int contained in the
singing box (the end result of evaluting `u`) and bind the variable
-`x` to that int.  So `x <- u` means "Sing me up an int, and I'll call
-it `x`".
+`x` to that int.  So `x <- u` means "Sing me up an int, which I'll call
+`x`".

(Note that the above "do" notation comes from Haskell. We're mentioning it here
@@ -372,8 +372,8 @@ them from hurting the people that use them or themselves.

# let unit x = Some x;;
val unit : 'a -> 'a option = <fun>
-               # let ( * ) u f = match u with None -> None | Some x -> f x;;
-               val ( * ) : 'a option -> ('a -> 'b option) -> 'b option = <fun>
+               # let ( >>= ) u f = match u with None -> None | Some x -> f x;;
+               val ( >>= ) : 'a option -> ('a -> 'b option) -> 'b option = <fun>

The parentheses is the magic for telling OCaml that the
function to be defined (in this case, the name of the function
@@ -382,44 +382,44 @@ them from hurting the people that use them or themselves.

# unit 2;;
- : int option = Some 2
-               # unit 2 * unit;;
+               # unit 2 >>= unit;;
- : int option = Some 2

# let divide x y = if 0 = y then None else Some (x/y);;
val divide : int -> int -> int option = <fun>
# divide 6 2;;
- : int option = Some 3
-               # unit 2 * divide 6;;
+               # unit 2 >>= divide 6;;
- : int option = Some 3

# divide 6 0;;
- : int option = None
-               # unit 0 * divide 6;;
+               # unit 0 >>= divide 6;;
- : int option = None

*      **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`.

Some examples of associativity in the option monad:

-               # Some 3 * unit * unit;;
+               # Some 3 >>= unit >>= unit;;
- : int option = Some 3
-               # Some 3 * (fun x -> unit x * unit);;
+               # Some 3 >>= (fun x -> unit x >>= unit);;
- : int option = Some 3

-               # Some 3 * divide 6 * divide 2;;
+               # Some 3 >>= divide 6 >>= divide 2;;
- : int option = Some 1
-               # Some 3 * (fun x -> divide 6 x * divide 2);;
+               # Some 3 >>= (fun x -> divide 6 x >>= divide 2);;
- : int option = Some 1

-               # Some 3 * divide 2 * divide 6;;
+               # Some 3 >>= divide 2 >>= divide 6;;
- : int option = None
-               # Some 3 * (fun x -> divide 2 x * divide 6);;
+               # Some 3 >>= (fun x -> divide 2 x >>= divide 6);;
- : int option = None

Of course, associativity must hold for *arbitrary* functions of
@@ -433,11 +433,11 @@ computations will again result in `None`; and if the value of
to `g y`.

*      **Right identity: unit is a right identity for bind.**  That is,
-       `u * unit == u` for all monad objects `u`.  For instance,
+       `u >>= unit == u` for all monad objects `u`.  For instance,

-               # Some 3 * unit;;
+               # Some 3 >>= unit;;
- : int option = Some 3
-               # None * unit;;
+               # None >>= unit;;
- : 'a option = None