towards monads: use u,v for monadic terms
[lambda.git] / week7.mdwn
index da4a4f4..9a88221 100644 (file)
@@ -1,10 +1,11 @@
 [[!toc]]
 
+
 Monads
 ------
 
 Start by (re)reading the discussion of monads in the lecture notes for
-week 6 [Towards Monads](http://lambda.jimpryor.net//week6/#index4h2).
+week 6 [[Towards Monads]].
 In those notes, we saw a way to separate thinking about error
 conditions (such as trying to divide by zero) from thinking about
 normal arithmetic computations.  We did this by making use of the
@@ -170,8 +171,47 @@ 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:
+
+       # type 'a list
+
+The unit/return operation is:
+
+       # let unit x = [x];;
+       val unit : 'a -> 'a list = <fun>
+
+That is, the simplest way to lift an 'a into an 'a list is just to make a
+singleton list of that 'a. Finally, the bind operation is:
+
+       # let bind m f = List.concat (List.map f m);;
+       val bind : 'a list -> ('a -> 'b list) -> 'b list = <fun>
+       
+What's going on here? Well, consider (List.map f m) first. This goes through all
+the members of the list m. There may be just a single member, if `m = unit a`
+for some a. Or on the other hand, there may be no members, or many members. In
+any case, we go through them in turn and feed them to f. Anything that gets fed
+to f will be an 'a. f takes those values, and for each one, returns a 'b list.
+For example, it might return a list of all that value's divisors. Then we'll
+have a bunch of 'b lists. The surrounding `List.concat ( )` converts that bunch
+of 'b lists 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
+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
+monadic systems.
 
-The Monad laws
+Many monadic systems will also define special-purpose operations that only make
+sense for that system.
+
+Although the unit and bind operation are defined differently for different
+monadic systems, there are some general rules they always have to follow.
+
+
+The Monad Laws
 --------------
 
 Just like good robots, monads must obey three laws designed to prevent
@@ -179,8 +219,8 @@ 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
-       object, we have `(unit x) * f == f x`.  For instance, `unit` is a
-       function of type `'a -> 'a option`, so we have
+       value, 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`:
 
 <pre>
 # let ( * ) m f = match m with None -> None | Some n -> f n;;
@@ -255,7 +295,11 @@ to `g r`.
 - : 'a option = None
 </pre>
 
-Now, if you studied algebra, you'll remember that a *monoid* is an
+
+More details about monads
+-------------------------
+
+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
@@ -263,10 +307,113 @@ serving as the left and right identity.  That is, temporarily using
 `n`, and `(a * b) * c == a * (b * c)` for all `a`, `b`, and `c`.  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 if we generalize bind so that both arguments are
-of type `'a -> 'a m`, then we get plain identity laws and
-associativity laws, and the monad laws are exactly like the monoid
-laws (see <http://www.haskell.org/haskellwiki/Monad_Laws>, near the bottom).
+different types.  But it's possible to make the connection between
+monads and monoids much closer. This is discussed in [[Advanced Notes/Monads in Category Theory]]. See also <http://www.haskell.org/haskellwiki/Monad_Laws>.
+
+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).
+
+*      [Philip Wadler. Monads for Functional Programming](http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf):
+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.
+       The use of monads to structure functional programs is described. Monads provide a convenient framework for simulating effects found in other languages, such as global state, exception handling, output, or non-determinism. Three case studies are looked at in detail: how monads ease the modification of a simple evaluator; how monads act as the basis of a datatype of arrays subject to in-place update; and how monads can be used to build parsers.
+
+*      [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.
+       This paper explores the use monads to structure functional programs. No prior knowledge of monads or category theory is required.
+       Monads increase the ease with which programs may be modified. They can mimic the effect of impure features such as exceptions, state, and continuations; and also provide effects not easily achieved with such features. The types of a program reflect which effects occur.
+       The first section is an extended example of the use of monads. A simple interpreter is modified to support various extra features: error messages, state, output, and non-deterministic choice. The second section describes the relation between monads and continuation-passing style. The third section sketches how monads are used in a compiler for Haskell that is written in Haskell.
+
+There's a long list of monad tutorials on the [[Offsite Reading]] page. Skimming the titles makes me laugh.
+
+In the presentation we gave above, which is the usual one in functional programming, 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, and define for example bind in terms of them. This is discussed some in the [[Advanced Notes/Monads in Category Theory]].
+
+
+Here are some of the specifics. You don't have to master these; they're collected here for your reference.
+
+You may sometimes see:
+
+       m >> n
+
+That just means:
+
+       m >>= fun _ -> n
+
+that is:
+
+       bind m (fun _ -> n)
+
+You could also do `bind m (fun x -> n)`; 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:
+
+       # let even x = (x mod 2 = 0);;
+       val g : int -> bool = <fun>
+
+`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 m -> bind m (fun x -> Some (g x));;
+       val lift : ('a -> 'b) -> 'a option -> 'b option = <fun>
+
+`lift even` will now be a function from `int option`s to `bool option`s. We can
+also define a lift operation for binary functions:
+
+       # let lift2 g = fun m n -> bind m (fun x -> bind n (fun y -> Some (g x y)));;
+       val lift2 : ('a -> 'b -> 'c) -> 'a option -> 'b option -> 'c option = <fun>
+
+`lift (+)` 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 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 pre-defined `unit` operation for the monad we're working with.
+
+In general, any lift/map operation can be relied on to satisfy these laws:
+
+       * lift id = id
+       * lift (compose f g) = compose (lift f) (lift g)
+
+where id is `fun x -> x` and `compose a b` is `fun x -> a (b x)`. If you think about the special case of the map operation on lists, this should make sense. `List.map id lst` should give you back `lst` again. And you'd expect these
+two computations to give the same result:
+
+       List.map (fun x -> f (g x)) lst
+
+       List.map f (List.map g lst)
+
+Another general monad operation is called `ap` in Haskell---short for "apply." (They also use `<*>`, but who can remember that?) This works like this:
+
+       ap [f] [x; y] = [f x; f y]
+       ap (Some f) (Some x) = Some (f x)
+
+and so on. Here are the laws that any ap operation can be relied on to satisfy:
+
+       ap (unit id) v = v
+       ap (ap (ap (return compose) u) v) w = ap u (ap v w)
+       ap (unit f) (unit x) = unit (f x)
+       ap u (unit y) = ap (unit (fun f -> f y)) 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
+we went from:
+
+       [[1]; [1;2]; [1;3]; [1;2;4]]
+
+to:
+
+       [1; 1; 2; 1; 3; 1; 2; 4]
+
+That is the `join` operation.
+
+All of these operations can be defined in terms of `bind` and `unit`; or alternatively, some of them can be taken as primitive and `bind` can be defined in terms of them. Here are various interdefinitions:
+
+       lift f m = ap (unit f) m
+       lift2 f m n = ap (lift f m) n = ap (ap (unit f) m) n
+       ap m n = lift2 id m n
+       lift f m = m >>= compose unit f
+       lift f m = ap (unit f) m
+       join m2 = m2 >>= id
+       m >>= f = join (lift f m)
+       m >> n = m >>= (fun _ -> n)
+       m >> n = lift2 (fun _ -> id) m n
+
 
 
 Monad outlook
@@ -278,10 +425,22 @@ which will enable us to model mutation: variables whose values appear
 to change as the computation progresses.  Later, we will study the
 Continuation monad.
 
+In the meantime, we'll look at several linguistic applications for monads, based
+on what's called the *reader monad*.
+
+
+The reader monad
+----------------
+
+Introduce
+
+Heim and Kratzer's "Predicate Abstraction Rule"
+
+
+
 The intensionality monad
 ------------------------
-
-In the meantime, we'll see a linguistic application for monads:
+...
 intensional function application.  In Shan (2001) [Monads for natural
 language semantics](http://arxiv.org/abs/cs/0205026v1), Ken shows that
 making expressions sensitive to the world of evaluation is