X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=week7.mdwn;h=7544425c4bbcca2c3a1b72cf0cf088199a18586f;hp=79983c3eb524ad560ae2d5f45a2bafb0b38d8da8;hb=d3ea4212bbca7a47f8aae537023852fd9a214389;hpb=01979f60c8474ffe20e4a1a20d59bfff5d3950c6 diff --git a/week7.mdwn b/week7.mdwn index 79983c3e..7544425c 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 =
@@ -165,7 +164,7 @@ theory of accommodation, and a theory of the situations in which
material within the sentence can satisfy presuppositions for other
material that otherwise would trigger a presupposition violation; but,
not surprisingly, these refinements will require some more
-sophisticated techniques than the super-simple option monad.]
+sophisticated techniques than the super-simple Option monad.]

@@ -228,7 +227,7 @@ that provides at least the following three elements:

So `unit` is a way to put something inside of a monadic box. It's crucial
to the usefulness of monads that there will be monadic boxes that
-	aren't the result of that operation. In the option/maybe monad, for
+	aren't the result of that operation. In the Option/Maybe monad, for
instance, there's also the empty box `None`. In another (whimsical)
example, you might have, in addition to boxes merely containing integers,
special boxes that contain integers and also sing a song when they're opened.
@@ -237,9 +236,9 @@ 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
+	what linguists usually mean by "binding." In our Option/Maybe monad, the
bind operation is:

let bind u f = match u with None -> None | Some x -> f x;;
@@ -261,7 +260,7 @@ that provides at least the following three elements:

The guts of the definition of the `bind` operation amount to
specifying how to unbox the monadic value `u`.  In the `bind`
-	operator for the option monad, we unboxed the monadic value by
+	operator for the Option monad, we unboxed the monadic value by
matching it with the pattern `Some x`---whenever `u`
happened to be a box containing an integer `x`, this allowed us to
get our hands on that `x` and feed it to `f`.
@@ -282,7 +281,7 @@ that provides at least the following three elements:
For each new monadic type, this has to be worked out in an
useful way.

-So the "option/maybe monad" consists of the polymorphic `option` type, the
+So the "Option/Maybe monad" consists of the polymorphic `option` type, the
`unit`/return function, and the `bind` function.

@@ -314,12 +313,12 @@ singing box (the end result of evaluting `u`) and bind the variable
`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
+because you're likely to see it when reading about monads. (See our page on [[Translating between OCaml Scheme and Haskell]].) It won't work in
OCaml. In fact, the `<-` symbol already means something different in OCaml,
having to do with mutable record fields. We'll be discussing mutation someday
soon.)

-As we proceed, we'll be seeing a variety of other monad systems. For example, another monad is the list monad. Here the monadic type is:
+As we proceed, we'll be seeing a variety of other monad systems. For example, another monad is the List monad. Here the monadic type is:

# type 'a list

@@ -346,7 +345,7 @@ of `'b list`s into a single `'b list`:
# List.concat [[1]; [1;2]; [1;3]; [1;2;4]]
- : int list = [1; 1; 2; 1; 3; 1; 2; 4]

-So now we've seen two monads: the option/maybe monad, and the list monad. For any
+So now we've seen two monads: the Option/Maybe monad, and the List monad. For any
monadic system, there has to be a specification of the complex monad type,
which will be parameterized on some simpler type `'a`, and the `unit`/return
operation, and the `bind` operation. These will be different for different
@@ -366,7 +365,7 @@ 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
+	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`:

@@ -379,14 +378,15 @@ them from hurting the people that use them or themselves.
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 equivalently `( >>= ) u f` instead of `>>= u
-	f`. Now, for a less trivial instance of a function from `int`s
-	to `int option`s:
+	f`.

# unit 2;;
- : int option = Some 2
# 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;;
@@ -402,12 +402,17 @@ them from hurting the people that use them or themselves.

*	**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`.
+	Wadler and others try to make this look nicer by phrasing it like this,
+	where U, V, and W are schematic for any expressions with the relevant monadic type:

-	Some examples of associativity in the option monad (bear in
+		(U >>= fun x -> V) >>= fun y -> W  ==  U >>= fun x -> (V >>= fun y -> W)
+
+	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):

@@ -426,15 +431,15 @@ them from hurting the people that use them or themselves.
# 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
-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
-`u` matches `Some x`, and `f x` evalutes to `None`, then both
-computations will again result in `None`; and if the value of
-`f x` matches `Some y`, then both computations will evaluate
-to `g y`.
+	Of course, associativity must hold for *arbitrary* functions of
+	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
+	`u` matches `Some x`, and `f x` evalutes to `None`, then both
+	computations will again result in `None`; and if the value of
+	`f x` matches `Some y`, then both computations will evaluate
+	to `g y`.

*	**Right identity: unit is a right identity for bind.**  That is,
`u >>= unit == u` for all monad objects `u`.  For instance,
@@ -457,34 +462,41 @@ 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.
+
+*	[Philip Wadler. The essence of functional programming](http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence.ps):
+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.

-*	[Philip Wadler. The essence of functional programming](http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence.ps):
-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 us 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.

@@ -507,7 +519,7 @@ The `lift` operation we asked you to define for last week's homework is a common
# let even x = (x mod 2 = 0);;
val g : int -> bool =

-`even` has the type `int -> bool`. Now what if we want to convert it into an operation on the option/maybe monad?
+`even` has the type `int -> bool`. Now what if we want to convert it into an operation on the Option/Maybe monad?

# let lift g = fun u -> bind u (fun x -> Some (g x));;
val lift : ('a -> 'b) -> 'a option -> 'b option =
@@ -520,7 +532,7 @@ also define a lift operation for binary functions:

`lift2 (+)` will now be a function from `int option`s  and `int option`s to `int option`s. This should look familiar to those who did the homework.

-The `lift` operation (just `lift`, not `lift2`) is sometimes also called the `map` operation. (In Haskell, they say `fmap` or `<\$>`.) And indeed when we're working with the list monad, `lift f` is exactly `List.map f`!
+The `lift` operation (just `lift`, not `lift2`) is sometimes also called the `map` operation. (In Haskell, they say `fmap` or `<\$>`.) And indeed when we're working with the List monad, `lift f` is exactly `List.map f`!

Wherever we have a well-defined monad, we can define a lift/map operation for that monad. The examples above used `Some (g x)` and so on; in the general case we'd use `unit (g x)`, using the specific `unit` operation for the monad we're working with.

@@ -547,7 +559,7 @@ and so on. Here are the laws that any `ap` operation can be relied on to satisfy
ap (unit f) (unit x) = unit (f x)
ap u (unit x) = ap (unit (fun f -> f x)) u

-Another general monad operation is called `join`. This is the operation that takes you from an iterated monad to a single monad. Remember when we were explaining the `bind` operation for the list monad, there was a step where
+Another general monad operation is called `join`. This is the operation that takes you from an iterated monad to a single monad. Remember when we were explaining the `bind` operation for the List monad, there was a step where
we went from:

[[1]; [1;2]; [1;3]; [1;2;4]]
@@ -577,15 +589,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