```+# let divide num den = if den = 0 then None else Some (num/den);;
+val divide : int -> int -> int option =
+```
+ +as basically a function from two integers to an integer, except with +this little bit of option frill, or option plumbing, on the side. -A note on notation: some people use the infix operator `>==` to stand +A note on notation: Haskell uses the infix operator `>>=` to stand for `bind`. I really hate that symbol. Following Wadler, I prefer to infix five-pointed star, or on a keyboard, `*`. @@ -108,40 +119,63 @@ them from hurting the people that use them or themselves. val ( * ) : 'a option -> ('a -> 'b option) -> 'b option = # let unit x = Some x;; val unit : 'a -> 'a option = + +# unit 2;; +- : int option = Some 2 # unit 2 * unit;; - : int option = Some 2 + +# divide 6 2;; +- : int option = Some 3 +# unit 2 * divide 6;; +- : int option = Some 3 + +# divide 6 0;; +- : int option = None +# unit 0 * divide 6;; +- : int option = None - The parentheses is the magic for telling Ocaml that the - function to be defined (in this case, the name of the function - is `*`, pronounced "bind") is an infix operator, so we write - `m * f` or `( * ) m f` instead of `* m f`. +The parentheses is the magic for telling Ocaml that the +function to be defined (in this case, the name of the function +is `*`, pronounced "bind") is an infix operator, so we write +`m * f` or `( * ) m f` instead of `* m f`. * Associativity: bind obeys a kind of associativity, like this: - (m * f) * g == m * (fun x -> f x * g) + `(m * f) * g == m * (fun x -> f x * g)` - If you don't understand why the lambda form is necessary, you need - to look again at the type of bind. This is important. + 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. - For an illustration of associativity in the option monad: + 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;;
+- : int option = Some 1
+# Some 3 * (fun x -> divide 6 x * divide 2);;
+- : int option = Some 1
+
+# Some 3 * divide 2 * divide 6;;
+- : int option = None
+# Some 3 * (fun x -> divide 2 x * divide 6);;
+- : int option = None
```
- Of course, associativity must hold for arbitrary functions of - type `'a -> M 'a`, 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 `m` - matches `None`, both computations will result in `None`; if - `m` matches `Some n`, and `f n` evalutes to `None`, then both - computations will again result in `None`; and if the value of - `f n` matches `Some r`, then both computations will evaluate - to `g r`. +Of course, associativity must hold for arbitrary functions of +type `'a -> M 'a`, 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 `m` +matches `None`, both computations will result in `None`; if +`m` matches `Some n`, and `f n` evalutes to `None`, then both +computations will again result in `None`; and if the value of +`f n` matches `Some r`, then both computations will evaluate +to `g r`. * Right identity: unit is a right identity for bind. That is, `m * unit == m` for all monad objects `m`. For instance, @@ -149,6 +183,8 @@ Some 3 * (fun x -> unit x * unit);;
``` # Some 3 * unit;;
- : int option = Some 3
+# None * unit;;
+- : 'a option = None
```