X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=week7.mdwn;h=abb6cfe82690c24556155b8dcf0b730bddcc2535;hp=e4e884bcbd6a38fcef93cdc50204bb1ca8aafa45;hb=0cd006d378ff7e001b4bc5203c97771eafd209da;hpb=6c44248b27640d43b5a683bb580f83e5cef08a28 diff --git a/week7.mdwn b/week7.mdwn index e4e884bc..abb6cfe8 100644 --- a/week7.mdwn +++ b/week7.mdwn @@ -58,12 +58,11 @@ operations. So we have to jack up the types of the inputs:
``` let div' (u:int option) (v:int option) =
-  match v with
+  match u with
None -> None
-    | Some 0 -> None
-	| Some y -> (match u with
-					  None -> None
-                    | Some x -> Some (x / y));;
+	| Some x -> (match v with
+				  Some 0 -> None
+				| Some y -> Some (x / y));;

(*
val div' : int option -> int option -> int option =
@@ -237,7 +236,7 @@ that provides at least the following three elements:
most straightforward way to lift an ordinary value into a monadic value
of the monadic type in question.

-*	Thirdly, an operation that's often called `bind`. This is another
+*	Thirdly, an operation that's often called `bind`. As we said before, this is another
unfortunate name: this operation is only very loosely connected to
what linguists usually mean by "binding." In our option/maybe monad, the
bind operation is:
@@ -310,8 +309,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
@@ -366,64 +365,69 @@ Just like good robots, monads must obey three laws designed to prevent
them from hurting the people that use them or themselves.

*	**Left identity: unit is a left identity for the bind operation.**
-	That is, for all `f:'a -> 'a m`, where `'a m` is a monadic
-	type, we have `(unit x) * f == f x`.  For instance, `unit` is itself
+	That is, for all `f:'a -> 'b m`, where `'b m` is a monadic
+	type, we have `(unit x) >>= f == f x`.  For instance, `unit` is itself
a function of type `'a -> 'a m`, so we can use it for `f`:

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

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
-	`u * f` or `( * ) u f` instead of `* u f`. Now:
+	is `>>=`, pronounced "bind") is an infix operator, so we write
+	`u >>= f` or equivalently `( >>= ) u f` instead of `>>= u
+	f`.

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

+	Now, for a less trivial instance of a function from `int`s to `int option`s:
+
# let divide x y = if 0 = y then None else Some (x/y);;
val divide : int -> int -> int option =
# 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`.
+	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 examples of associativity in the option monad (bear in
+	mind that in the Ocaml implementation of integer division, 2/3
+	evaluates to zero, throwing away the remainder):

-		# 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
-type `'a -> 'a m`, where `m` is the monad type.  It's easy to
+type `'a -> 'b m`, 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 `u`
matches `None`, both computations will result in `None`; if
@@ -433,11 +437,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

If you studied algebra, you'll remember that a *monoid* is an
associative operation with a left and right identity.  For instance,
the natural numbers along with multiplication form a monoid with 1
-serving as the left and right identity.  That is, temporarily using
-`*` to mean arithmetic multiplication, `1 * u == u == u * 1` for all
+serving as the left and right identity.  That is, `1 * u == u == u * 1` for all
`u`, and `(u * v) * w == u * (v * w)` for all `u`, `v`, and `w`.  As
presented here, a monad is not exactly a monoid, because (unlike the
arguments of a monoid operation) the two arguments of the bind are of
different types.  But it's possible to make the connection between
monads and monoids much closer. This is discussed in [Monads in Category

Here are some papers that introduced monads into functional programming:

-*	[Eugenio Moggi, Notions of Computation and Monads](http://www.disi.unige.it/person/MoggiE/ftp/ic91.pdf): Information and Computation 93 (1) 1991.
+*	[Eugenio Moggi, Notions of Computation and Monads](http://www.disi.unige.it/person/MoggiE/ftp/ic91.pdf): Information and Computation 93 (1) 1991. Would be very difficult reading for members of this seminar. However, the following two papers should be accessible.
+
+invited talk, *19'th Symposium on Principles of Programming Languages*, ACM Press, Albuquerque, January 1992.
+

in M. Broy, editor, *Marktoberdorf Summer School on Program Design
Calculi*, Springer Verlag, NATO ASI Series F: Computer and systems
sciences, Volume 118, August 1992. Also in J. Jeuring and E. Meijer,
editors, *Advanced Functional Programming*, Springer Verlag,
-LNCS 925, 1995. Some errata fixed August 2001.  This paper has a great first
-line: **Shall I be pure, or impure?**
+LNCS 925, 1995. Some errata fixed August 2001.

-invited talk, *19'th Symposium on Principles of Programming Languages*, ACM Press, Albuquerque, January 1992.
-
-
-*	[Daniel Friedman. A Schemer's View of Monads](/schemersviewofmonads.ps): from  but the link above is to a local copy.

-There's a long list of monad tutorials on the [[Offsite Reading]] page. Skimming the titles makes me laugh.
+There's a long list of monad tutorials on the [[Offsite Reading]] page. (Skimming the titles is somewhat amusing.) If you are confused by monads, make use of these resources. Read around until you find a tutorial pitched at a level that's helpful for you.

In the presentation we gave above---which follows the functional programming conventions---we took `unit`/return and `bind` as the primitive operations. From these a number of other general monad operations can be derived. It's also possible to take some of the others as primitive. The [Monads in Category

Here are some of the other general monad operations. You don't have to master these; they're collected here for your reference.

@@ -499,7 +500,7 @@ that is:

You could also do `bind u (fun x -> v)`; we use the `_` for the function argument to be explicit that that argument is never going to be used.

-The `lift` operation we asked you to define for last week's homework is a common operation. The second argument to `bind` converts `'a` values into `'b m` values---that is, into instances of the monadic type. What if we instead had a function that merely converts `'a` values into `'b` values, and we want to use it with our monadic type. Then we "lift" that function into an operation on the monad. For example:
+The `lift` operation we asked you to define for last week's homework is a common operation. The second argument to `bind` converts `'a` values into `'b m` values---that is, into instances of the monadic type. What if we instead had a function that merely converts `'a` values into `'b` values, and we want to use it with our monadic type? Then we "lift" that function into an operation on the monad. For example:

# let even x = (x mod 2 = 0);;
val g : int -> bool =
@@ -574,15 +575,15 @@ Monad outlook
-------------

We're going to be using monads for a number of different things in the
-weeks to come.  The first main application will be the State monad,
+weeks to come.  One major application will be the State monad,
which will enable us to model mutation: variables whose values appear
to change as the computation progresses.  Later, we will study the