X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=week7.mdwn;h=7544425c4bbcca2c3a1b72cf0cf088199a18586f;hp=abb6cfe82690c24556155b8dcf0b730bddcc2535;hb=d3ea4212bbca7a47f8aae537023852fd9a214389;hpb=c297b0b6a6f504abb4f3f95e3015378192ca5664 diff --git a/week7.mdwn b/week7.mdwn index abb6cfe8..7544425c 100644 --- a/week7.mdwn +++ b/week7.mdwn @@ -164,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.] Monads in General @@ -227,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. @@ -238,7 +238,7 @@ that provides at least the following three elements: * 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;; @@ -260,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`. @@ -281,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. @@ -313,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 @@ -345,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 @@ -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`. - Some examples of associativity in the option monad (bear in + 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: + + (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 -> '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`. + 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, @@ -458,7 +463,16 @@ 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 Theory](/advanced_topics/monads_in_category_theory). -See also . + +See also: + +* [Haskell wikibook on Monad Laws](http://www.haskell.org/haskellwiki/Monad_Laws). +* [Yet Another Haskell Tutorial on Monad Laws](http://en.wikibooks.org/wiki/Haskell/YAHT/Monads#Definition) +* [Haskell wikibook on Understanding Monads](http://en.wikibooks.org/wiki/Haskell/Understanding_monads) +* [Haskell wikibook on Advanced Monads](http://en.wikibooks.org/wiki/Haskell/Advanced_monads) +* [Haskell wikibook on do-notation](http://en.wikibooks.org/wiki/Haskell/do_Notation) +* [Yet Another Haskell Tutorial on do-notation](http://en.wikibooks.org/wiki/Haskell/YAHT/Monads#Do_Notation) + Here are some papers that introduced monads into functional programming: @@ -505,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 = @@ -518,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. @@ -545,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]] @@ -583,7 +597,7 @@ Continuation monad. But first, we'll look at several linguistic applications for monads, based on what's called the *Reader monad*. -##[[Reader monad for Variable Binding]]## +##[[Reader Monad for Variable Binding]]## -##[[Reader monad for Intensionality]]## +##[[Reader Monad for Intensionality]]##