+# 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 =+

-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 = NoneNow, if you studied algebra, you'll remember that a *monoid* is an @@ -162,7 +198,7 @@ arguments of a monoid operation) the two arguments of the bind are of different types. But if we generalize bind so that both arguments are of type `'a -> M 'a`, then we get plain identity laws and associativity laws, and the monad laws are exactly like the monoid -laws (see