unstable state of gsv discussion
[lambda.git] / topics / week7_introducing_monads.mdwn
index 9fa55a6..06dd06e 100644 (file)
@@ -122,9 +122,9 @@ Here are the types of our crucial functions, together with our pronunciation, an
 
 > For all these reasons, we're thinking it will be clearer in our discussion to use a different name. In the class presentation Jim called it `𝟭`; and in an earlier draft of this page we (only) called it `mid` ("m" plus "identity"); but now we're trying out `⇧` as a symbolic alternative. But in the end, we might switch to just using `η`.
 
-<code>m$ or mapply (/εm@plai/): <u>P -> Q</u> -> <u>P</u> -> <u>Q</u></code>
+<code>¢ or mapply (/εm@plai/): <u>P -> Q</u> -> <u>P</u> -> <u>Q</u></code>
 
-> We'll use `m$` as a left-associative infix operator, reminiscent of (the right-associative) `$` which is just ordinary function application (also expressed by mere left-associative juxtaposition). In the class presentation Jim called `m$` `⚫`. In Haskell, it's called `Control.Monad.ap` or `Control.Applicative.<*>`.
+> We'll use `¢` as a left-associative infix operator, reminiscent of (the right-associative) `$` which is just ordinary function application (also expressed by mere left-associative juxtaposition). In the class presentation Jim called `¢` `⚫`; and in an earlier draft of this page we called it `m$`. In Haskell, it's called `Control.Monad.ap` or `Control.Applicative.<*>`.
 
 <code>&lt;=&lt; or mcomp : (Q -> <u>R</u>) -> (P -> <u>Q</u>) -> (P -> <u>R</u>)</code>
 
@@ -171,27 +171,27 @@ has to obey the following Map Laws:
        Moreover, with `map2` in hand, `map3`, `map4`, ... `mapN` are easily definable.) These
        have to obey the following MapN Laws:
 
-    1. <code>⇧ (id : P->P) : <u>P</u> -> <u>P</u></code> is a left identity for `m$`, that is: `(⇧ id) m$ xs = xs`
-    2. `⇧ (f a) = (⇧ f) m$ (⇧ a)`
-    3. The `map2`ing of composition onto boxes `fs` and `gs` of functions, when `m$`'d to a box `xs` of arguments == the `m$`ing of `fs` to the `m$`ing of `gs` to xs: `(⇧ (○) m$ fs m$ gs) m$ xs = fs m$ (gs m$ xs)`.
-    4. When the arguments (the right-hand operand of `m$`) are an `⇧`'d value, the order of `m$`ing doesn't matter: `fs m$ (⇧ x) = ⇧ ($x) m$ fs`. (Though note that it's `⇧ ($x)`, or `⇧ (\f. f x)` that gets `m$`d onto `fs`, not the original `⇧ x`.) Here's an example where the order *does* matter: `[succ,pred] m$ [1,2] == [2,3,0,1]`, but `[($1),($2)] m$ [succ,pred] == [2,0,3,1]`. This Law states a class of cases where the order is guaranteed not to matter.
-    5. A consequence of the laws already stated is that when the _left_-hand operand of `m$` is a `⇧`'d value, the order of `m$`ing doesn't matter either: `⇧ f m$ xs == map (flip ($)) xs m$ ⇧ f`.
+    1. <code>⇧(id : P->P) : <u>P</u> -> <u>P</u></code> is a left identity for `¢`, that is: `(⇧id) ¢ xs = xs`
+    2. `⇧(f a) = (⇧f) ¢ (⇧a)`
+    3. The `map2`ing of composition onto boxes `fs` and `gs` of functions, when `¢`'d to a box `xs` of arguments == the `¢`ing of `fs` to the `¢`ing of `gs` to xs: `(⇧(○) ¢ fs ¢ gs) ¢ xs = fs ¢ (gs ¢ xs)`.
+    4. When the arguments (the right-hand operand of `¢`) are an `⇧`'d value, the order of `¢`ing doesn't matter: `fs ¢ (⇧x) = ⇧($x) ¢ fs`. (Though note that it's `⇧($x)`, or `⇧(\f. f x)` that gets `¢`d onto `fs`, not the original `⇧x`.) Here's an example where the order *does* matter: `[succ,pred] ¢ [1,2] == [2,3,0,1]`, but `[($1),($2)] ¢ [succ,pred] == [2,0,3,1]`. This Law states a class of cases where the order is guaranteed not to matter.
+    5. A consequence of the laws already stated is that when the _left_-hand operand of `¢` is a `⇧`'d value, the order of `¢`ing doesn't matter either: `⇧f ¢ xs == map (flip ($)) xs ¢ ⇧f`.
 
 <!-- Probably there's a shorter proof, but:
-   ⇧ T m$ xs m$ ⇧ f
-== ⇧ T m$ ((⇧ id) m$ xs) m$ ⇧ f, by 1
-== ⇧ (○) m$ ⇧ T m$ ⇧ id m$ xs m$ ⇧ f, by 3
-== ⇧ ($id) m$ (⇧ (○) m$ ⇧ T) m$ xs m$ ⇧ f, by 4
-== ⇧ (○) m$ ⇧ ($id) m$ ⇧ (○) m$ ⇧ T m$ xs m$ ⇧ f, by 3
-== ⇧ ((○) ($id)) m$ ⇧ (○) m$ ⇧ T m$ xs m$ ⇧ f, by 2
-== ⇧ ((○) ($id) (○)) m$ ⇧ T m$ xs m$ ⇧ f, by 2
-== ⇧ id m$ ⇧ T m$ xs m$ ⇧ f, by definitions of ○ and $
-== ⇧ T m$ xs m$ ⇧ f, by 1
-== ⇧ ($f) m$ (⇧ T m$ xs), by 4
-== ⇧ (○) m$ ⇧ ($f) m$ ⇧ T m$ xs, by 3
-== ⇧ ((○) ($f)) m$ ⇧ T m$ xs, by 2
-== ⇧ ((○) ($f) T) m$ xs, by 2
-== ⇧ f m$ xs, by definitions of ○ and $ and T == flip ($)
+   ⇧T ¢ xs ¢ ⇧f
+== ⇧T ¢ ((⇧id) ¢ xs) ¢ ⇧f, by 1
+== ⇧(○) ¢ ⇧T ¢ ⇧id ¢ xs ¢ ⇧f, by 3
+== ⇧($id) ¢ (⇧(○) ¢ ⇧T) ¢ xs ¢ ⇧f, by 4
+== ⇧(○) ¢ ⇧($id) ¢ ⇧(○) ¢ ⇧T ¢ xs ¢ ⇧f, by 3
+== ⇧((○) ($id)) ¢ ⇧(○) ¢ ⇧T ¢ xs ¢ ⇧f, by 2
+== ⇧((○) ($id) (○)) ¢ ⇧T ¢ xs ¢ ⇧f, by 2
+== ⇧id ¢ ⇧T ¢ xs ¢ ⇧f, by definitions of ○ and $
+== ⇧T ¢ xs ¢ ⇧f, by 1
+== ⇧($f) ¢ (⇧T ¢ xs), by 4
+== ⇧(○) ¢ ⇧($f) ¢ ⇧T ¢ xs, by 3
+== ⇧((○) ($f)) ¢ ⇧T ¢ xs, by 2
+== ⇧((○) ($f) T) ¢ xs, by 2
+== ⇧f ¢ xs, by definitions of ○ and $ and T == flip ($)
 -->
 
 *   ***Monad*** (or "Composables") A MapNable box type is a *Monad* if there
@@ -214,13 +214,13 @@ has to obey the following Map Laws:
 
         u >>= (\a -> k a >>= j) == (u >>= k) >>= j
         u >>= ⇧ == u
-        ⇧ a >>= k == k a
+        ⇧a >>= k == k a
 
     (Also, Haskell calls `⇧` `return` or `pure`, but we've stuck to our terminology in this context.) Some authors try to make the first of those Laws look more symmetrical by writing it as:
 
         (A >>= \a -> B) >>= \b -> C == A >>= (\a -> B >>= \b -> C)
 
-    If you have any of `mcomp`, `mpmoc`, `mbind`, or `join`, you can use them to define the others. Also, with these functions you can define `m$` and `map2` from *MapNables*. So with Monads, all you really need to get the whole system of functions are a definition of `⇧`, on the one hand, and one of `mcomp`, `mbind`, or `join`, on the other.
+    If you have any of `mcomp`, `mpmoc`, `mbind`, or `join`, you can use them to define the others. Also, with these functions you can define `¢` and `map2` from *MapNables*. So with Monads, all you really need to get the whole system of functions are a definition of `⇧`, on the one hand, and one of `mcomp`, `mbind`, or `join`, on the other.
 
 
     > <small>In Category Theory discussion, the Monad Laws are instead expressed in terms of `join` (which they call `μ`) and `⇧` (which they call `η`). These are assumed to be "natural transformations" for their box type, which means that they satisfy these equations with that box type's `map`:
@@ -271,22 +271,22 @@ j >=> k ≡= \a. (j a >>= k)
 u >>= k == (id >=> k) u; or ((\(). u) >=> k) ()
 u >>= k == join (map k u)
 join w == w >>= id
-map2 f xs ys == xs >>= (\x. ys >>= (\y. ⇧ (f x y)))
-map2 f xs ys == (map f xs) m$ ys, using m$ as an infix operator
-fs m$ xs == fs >>= (\f. map f xs)
-m$ == map2 id
-map f xs == ⇧ f m$ xs
+map2 f xs ys == xs >>= (\x. ys >>= (\y. ⇧(f x y)))
+map2 f xs ys == (map f xs) ¢ ys, using ¢ as an infix operator
+fs ¢ xs == fs >>= (\f. map f xs)
+¢ == map2 id
+map f xs == ⇧f ¢ xs
 map f u == u >>= ⇧ ○ f
 </pre>
 
 
 Here are some other monadic notion that you may sometimes encounter:
 
-* <code>mzero</code> is a value of type <code><u>α</u></code> that is exemplified by `Nothing` for the box type `Maybe α` and by `[]` for the box type `List α`. It has the behavior that `anything m$ mzero == mzero == mzero m$ anything == mzero >>= anything`. In Haskell, this notion is called `Control.Applicative.empty` or `Control.Monad.mzero`.
+* <code>mzero</code> is a value of type <code><u>α</u></code> that is exemplified by `Nothing` for the box type `Maybe α` and by `[]` for the box type `List α`. It has the behavior that `anything ¢ mzero == mzero == mzero ¢ anything == mzero >>= anything`. In Haskell, this notion is called `Control.Applicative.empty` or `Control.Monad.mzero`.
 
-* Haskell has a notion `>>` definable as `\u v. map (const id) u m$ v`, or as `\u v. u >>= const v`. This is often useful, and `u >> v` won't in general be identical to just `v`. For example, using the box type `List α`, `[1,2,3] >> [4,5] == [4,5,4,5,4,5]`. But in the special case of `mzero`, it is a consequence of what we said above that `anything >> mzero == mzero`. Haskell also calls `>>` `Control.Applicative.*>`.
+* Haskell has a notion `>>` definable as `\u v. map (const id) u ¢ v`, or as `\u v. u >>= const v`. This is often useful, and `u >> v` won't in general be identical to just `v`. For example, using the box type `List α`, `[1,2,3] >> [4,5] == [4,5,4,5,4,5]`. But in the special case of `mzero`, it is a consequence of what we said above that `anything >> mzero == mzero`. Haskell also calls `>>` `Control.Applicative.*>`.
 
-* Haskell has a correlative notion `Control.Applicative.<*`, definable as `\u v. map const u m$ v`. For example, `[1,2,3] <* [4,5] == [1,1,2,2,3,3]`. <!-- You might expect Haskell to call `<*` `<<`, but they don't. I thought they used to use `<<` for `flip (>>)` instead, but now I can't confirm that this was ever the case. -->
+* Haskell has a correlative notion `Control.Applicative.<*`, definable as `\u v. map const u ¢ v`. For example, `[1,2,3] <* [4,5] == [1,1,2,2,3,3]`. <!-- You might expect Haskell to call `<*` `<<`, but they don't. I thought they used to use `<<` for `flip (>>)` instead, but now I can't confirm that this was ever the case. -->
 
 * <code>mapconst</code> is definable as `map ○ const`. For example `mapconst 4 [1,2,3] == [4,4,4]`. Haskell calls `mapconst` `<$` in `Data.Functor` and `Control.Applicative`. They also use `$>` for `flip mapconst`, and `Control.Monad.void` for `mapconst ()`.
 
@@ -355,13 +355,13 @@ For example:
 
 `j 7` produced `[49, 14]`, which after being fed through `k` gave us `[49, 50, 14, 15]`.
 
-Contrast that to `m$` (`mapply`), which operates not on two *box-producing functions*, but instead on two *boxed type values*, one containing functions to be applied to the values in the other box, via some predefined scheme. Thus:
+Contrast that to `¢` (`mapply`), which operates not on two *box-producing functions*, but instead on two *boxed type values*, one containing functions to be applied to the values in the other box, via some predefined scheme. Thus:
 
     let js = [(\a->a*a),(\a->a+a)] in
     let xs = [7, 5] in
     mapply js xs ==> [49, 25, 14, 10]
 
-These implementations of `<=<` and `m$` for lists use the "crossing" strategy for pairing up multiple lists, as opposed to the "zipping" strategy. Nothing forces that choice; you could also define `m$` using the "zipping" strategy instead. (But then you wouldn't be able to build a corresponding Monad; see below.) Haskell talks of the List Monad in the first case, and the ZipList Applicative in the second case.
+These implementations of `<=<` and `¢` for lists use the "crossing" strategy for pairing up multiple lists, as opposed to the "zipping" strategy. Nothing forces that choice; you could also define `¢` using the "zipping" strategy instead. (But then you wouldn't be able to build a corresponding Monad; see below.) Haskell talks of the List Monad in the first case, and the ZipList Applicative in the second case.
 
 Sticking with the "crossing" strategy, here's how to motivate our implementation of `<=<`. Recall that we have on the one hand, an operation `filter` for lists, that applies a predicate to each element of the list, and returns a list containing only those elements which satisfied the predicate. But the elements it does retain, it retains unaltered. On the other hand, we have the operation `map` for lists, that is capable of _changing_ the list elements in the result. But it doesn't have the power to throw list elements away; elements in the source map one-to-one to elements in the result. In many cases, we want something in between `filter` and `map`. We want to be able to ignore or discard some list elements, and possibly also to change the list elements we keep. One way of doing this is to have a function `optmap`, defined like this:
 
@@ -380,9 +380,9 @@ That can be helpful, but it only enables us to have _zero or one_ elements in th
     let rec catmap (k : α -> β list) (xs : α list) : β list =
       match xs with
       | [] -> []
-      | x' :: xs' -> List.append (k x') (catmap f xs')
+      | x' :: xs' -> List.append (k x') (catmap k xs')
 
-Now we can have as many elements in the result for a given `α` as `k` cares to return. Another way to write `catmap k xs` is as (Haskell) `concat (map k cs)` or (OCaml) `List.flatten (List.map k xs)`. And this is just the definition of `mbind` or `>>=` for the List Monad. The definition of `mcomp` or `<=<`, that we gave above, differs only in that it's the way to compose two functions `j` and `k`, that you'd want to `catmap`, rather than the way to `catmap` one of those functions over a value that's already a list.
+Now we can have as many elements in the result for a given `α` as `k` cares to return. Another way to write `catmap k xs` is as (Haskell) `concat (map k xs)` or (OCaml) `List.flatten (List.map k xs)`. And this is just the definition of `mbind` or `>>=` for the List Monad. The definition of `mcomp` or `<=<`, that we gave above, differs only in that it's the way to compose two functions `j` and `k`, that you'd want to `catmap`, rather than the way to `catmap` one of those functions over a value that's already a list.
 
 This example is a good intuitive basis for thinking about the notions of `mbind` and `mcomp` more generally. Thus `mbind` for the option/Maybe type takes an option value, applies `k` to its element (if there is one), and returns the resulting option value. `mbind` for a tree with `α`-labeled leaves would apply `k` to each of the leaves, and return a tree containing arbitrarily large subtrees in place of all its former leaves, depending on what `k` returned.
 
@@ -414,19 +414,19 @@ For the first failure, we noted that it's easy to define a `map` operation for t
 
 But if on the other hand, your box type is `α -> R`, you'll find that there is no way to define a `map` operation that takes arbitrary functions of type `P -> Q` and values of the boxed type <code><u>P</u></code>, that is `P -> R`, and returns values of the boxed type <code><u>Q</u></code>.
 
-For the second failure, that is cases of Mappables that are not MapNables, we cited box types like `(R, α)`, for arbitrary fixed types `R`. The `map` operation for these is defined by `map f (r,a) = (r, f a)`. For certain choices of `R` these can be MapNables too. The easiest case is when `R` is the type of `()`. But when we look at the MapNable Laws, we'll see that they impose constraints we cannot satisfy for *every* choice of the fixed type `R`. Here's why. We'll need to define `⇧ a = (r0, a)` for some specific `r0` of type `R`. The choice can't depend on the value of `a`, because `⇧` needs to work for `a`s of _any_ type. Then the MapNable Laws will entail:
+For the second failure, that is cases of Mappables that are not MapNables, we cited box types like `(R, α)`, for arbitrary fixed types `R`. The `map` operation for these is defined by `map f (r,a) = (r, f a)`. For certain choices of `R` these can be MapNables too. The easiest case is when `R` is the type of `()`. But when we look at the MapNable Laws, we'll see that they impose constraints we cannot satisfy for *every* choice of the fixed type `R`. Here's why. We'll need to define `⇧a = (r0, a)` for some specific `r0` of type `R`. The choice can't depend on the value of `a`, because `⇧` needs to work for `a`s of _any_ type. Then the MapNable Laws will entail:
 
-    1. (r0,id) m$ (r,x) == (r,x)
-    2. (r0,f x) == (r0,f) m$ (r0,x)
-    3. (r0,(○)) m$ (r'',f) m$ (r',g) m$ (r,x) == (r'',f) m$ ((r',g) m$ (r,x))
-    4. (r'',f) m$ (r0,x) == (r0,($x)) m$ (r'',f)
-    5. (r0,f) m$ (r,x) == (r,($x)) m$ (r0,f)
+    1. (r0,id) ¢ (r,x) == (r,x)
+    2. (r0,f x) == (r0,f) ¢ (r0,x)
+    3. (r0,(○)) ¢ (r'',f) ¢ (r',g) ¢ (r,x) == (r'',f) ¢ ((r',g) ¢ (r,x))
+    4. (r'',f) ¢ (r0,x) == (r0,($x)) ¢ (r'',f)
+    5. (r0,f) ¢ (r,x) == (r,($x)) ¢ (r0,f)
 
-Now we are not going to be able to write a `m$` function that inspects the second element of its left-hand operand to check if it's the `id` function; the identity of functions is not decidable. So the only way to satisfy Law 1 will be to have the first element of the result (`r`) be taken from the first element of the right-hand operand in _all_ the cases when the first element of the left-hand operand is `r0`. But then that means that the result of the lhs of Law 5 will also have a first element of `r`; so, turning now to the rhs of Law 5, we see that `m$` must use the first element of its _left_-hand operand (here again `r`) at least in those cases when the first element of its right-hand operand is `r0`. If our `R` type has a natural *monoid* structure, we could just let `r0` be the monoid's identity, and have `m$` combine other `R`s using the monoid's operation. Alternatively, if the `R` type is one that we can safely apply the predicate `(r0==)` to, then we could define `m$` something like this:
+Now we are not going to be able to write a `¢` function that inspects the second element of its left-hand operand to check if it's the `id` function; the identity of functions is not decidable. So the only way to satisfy Law 1 will be to have the first element of the result (`r`) be taken from the first element of the right-hand operand in _all_ the cases when the first element of the left-hand operand is `r0`. But then that means that the result of the lhs of Law 5 will also have a first element of `r`; so, turning now to the rhs of Law 5, we see that `¢` must use the first element of its _left_-hand operand (here again `r`) at least in those cases when the first element of its right-hand operand is `r0`. If our `R` type has a natural *monoid* structure, we could just let `r0` be the monoid's identity, and have `¢` combine other `R`s using the monoid's operation. Alternatively, if the `R` type is one that we can safely apply the predicate `(r0==)` to, then we could define `¢` something like this:
 
-    let (m$) (r1,f) (r2,x) = ((if r0==r1 then r2 else if r0==r2 then r1 else ...), ...)
+    let (¢) (r1,f) (r2,x) = ((if r0==r1 then r2 else if r0==r2 then r1 else ...), ...)
 
-But for some types neither of these will be the case. For function types, as we already mentioned, `==` is not decidable. If the functions have suitable types, they do form a monoid with `○` as the operation and `id` as the identity; but many function types won't be such that arbitrary functions of that type are composable. So when `R` is the type of functions from `int`s to `bool`s, for example, we won't have any way to write a `m$` that satisfies the constraints stated above.
+But for some types neither of these will be the case. For function types, as we already mentioned, `==` is not decidable. If the functions have suitable types, they do form a monoid with `○` as the operation and `id` as the identity; but many function types won't be such that arbitrary functions of that type are composable. So when `R` is the type of functions from `int`s to `bool`s, for example, we won't have any way to write a `¢` that satisfies the constraints stated above.
 
 For the third failure, that is examples of MapNables that aren't Monads, we'll just state that lists where the `map2` operation is taken to be zipping rather than taking the Cartesian product (what in Haskell are called `ZipList`s), these are claimed to exemplify that failure. But we aren't now in a position to demonstrate that to you.
 
@@ -466,4 +466,4 @@ Here is some other reading:
 *      [Haskell wikibook on Advanced Monads](http://en.wikibooks.org/wiki/Haskell/Advanced_monads)
 *      [Haskell wiki on Monad Laws](http://www.haskell.org/haskellwiki/Monad_laws)
 
-There's a long list of monad tutorials linked at the [[Haskell wiki|https://wiki.haskell.org/Monad_tutorials_timeline]] (we linked to this at the top of the page), and on our own [[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.
+There's a long list of monad tutorials linked at the [[Haskell wiki|https://wiki.haskell.org/Monad_tutorials_timeline]] (we linked to this at the top of the page), and on our own [[Offsite Reading|/readings]] 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.