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
because you're likely to see it when reading about monads. It won't work in
# 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
# 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
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