X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=towards_monads.mdwn;h=378310f9701ab2cb8bffccfd30dce4476dc17b18;hp=223c592bc128b77b34c94de0db6420690b478fd5;hb=53be231576f6b0d8b6452fceac662158eea1d710;hpb=93d67277339f0aed8184a14bbc35ec5060a0c031 diff --git a/towards_monads.mdwn b/towards_monads.mdwn index 223c592b..378310f9 100644 --- a/towards_monads.mdwn +++ b/towards_monads.mdwn @@ -1,7 +1,7 @@ Dividing by zero ---------------- -Integer division operation presupposes that its second argument +Integer division presupposes that its second argument (the divisor) is not zero, upon pain of presupposition failure. Here's what my OCaml interpreter says: @@ -10,7 +10,7 @@ Here's what my OCaml interpreter says: So we want to explicitly allow for the possibility that division will return something other than a number. -We'll use OCaml's option type, which works like this: +We'll use OCaml's `option` type, which works like this: # type 'a option = None | Some of 'a;; # None;; @@ -19,12 +19,13 @@ We'll use OCaml's option type, which works like this: - : int option = Some 3 So if a division is normal, we return some number, but if the divisor is -zero, we return None. As a mnemonic aid, we'll append a `'` to the end of our new divide function. +zero, we return `None`. As a mnemonic aid, we'll append a `'` to the end of our new divide function.
 let div' (x:int) (y:int) =
-  match y with 0 -> None |
-               _ -> Some (x / y);;
+  match y with
+	  0 -> None
+    | _ -> Some (x / y);;
 
 (*
 val div' : int -> int -> int option = fun
@@ -35,7 +36,7 @@ val div' : int -> int -> int option = fun
 # div' (div' 12 3) 2;;
 Characters 4-14:
   div' (div' 12 3) 2;;
-      ^^^^^^^^^^
+        ^^^^^^^^^^
 Error: This expression has type int option
        but an expression was expected of type int
 *)
@@ -47,11 +48,13 @@ the output of the safe-division function as input for further division
 operations.  So we have to jack up the types of the inputs:
 
 
-let div' (x:int option) (y:int option) =
-  match y with None -> None |
-               Some 0 -> None |
-               Some n -> (match x with None -> None |
-                                       Some m -> Some (m / n));;
+let div' (u:int option) (v:int option) =
+  match v with
+	  None -> None
+    | Some 0 -> None
+	| Some y -> (match u with
+					  None -> None
+                    | Some x -> Some (x / y));;
 
 (*
 val div' : int option -> int option -> int option = 
@@ -71,23 +74,25 @@ I prefer to line up the `match` alternatives by using OCaml's
 built-in tuple type:
 
 
-let div' (x:int option) (y:int option) =
-  match (x, y) with (None, _) -> None |
-                    (_, None) -> None |
-                    (_, Some 0) -> None |
-                    (Some m, Some n) -> Some (m / n);;
+let div' (u:int option) (v:int option) =
+  match (u, v) with
+	  (None, _) -> None
+    | (_, None) -> None
+    | (_, Some 0) -> None
+	| (Some x, Some y) -> Some (x / y);;
 
So far so good. But what if we want to combine division with other arithmetic operations? We need to make those other operations -aware of the possibility that one of their arguments will trigger a +aware of the possibility that one of their arguments has triggered a presupposition failure:
-let add' (x:int option) (y:int option) =
-  match (x, y) with (None, _) -> None |
-                    (_, None) -> None |
-                    (Some m, Some n) -> Some (m + n);;
+let add' (u:int option) (v:int option) =
+  match (u, v) with
+	  (None, _) -> None
+    | (_, None) -> None
+    | (Some x, Some y) -> Some (x + y);;
 
 (*
 val add' : int option -> int option -> int option = 
@@ -107,15 +112,16 @@ Haskell, etc., is to define a `bind` operator (the name `bind` is not
 well chosen to resonate with linguists, but what can you do). To continue our mnemonic association, we'll put a `'` after the name "bind" as well.
 
 
-let bind' (x: int option) (f: int -> (int option)) =
-  match x with None -> None |
-               Some n -> f n;;
+let bind' (u: int option) (f: int -> (int option)) =
+  match u with
+	  None -> None
+    | Some x -> f x;;
 
-let add' (x: int option) (y: int option)  =
-  bind' x (fun x -> bind' y (fun y -> Some (x + y)));;
+let add' (u: int option) (v: int option)  =
+  bind' u (fun x -> bind' v (fun y -> Some (x + y)));;
 
-let div' (x: int option) (y: int option) =
-  bind' x (fun x -> bind' y (fun y -> if (0 = y) then None else Some (x / y)));;
+let div' (u: int option) (v: int option) =
+  bind' u (fun x -> bind' v (fun y -> if (0 = y) then None else Some (x / y)));;
 
 (*
 #  div' (div' (Some 12) (Some 2)) (Some 4);;