X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=list_monad_as_continuation_monad.mdwn;h=e4772f88888a50876a370d8af6c53d88ad1da608;hp=7a57ea7b73c5a9565f7644311ef8737f88200d4f;hb=26319cf2ffc188af7fc324143881d45fd7c322c8;hpb=d9bf1d89baaef4a0ceeb5c84db4d2a7172aaf400 diff --git a/list_monad_as_continuation_monad.mdwn b/list_monad_as_continuation_monad.mdwn index 7a57ea7b..e4772f88 100644 --- a/list_monad_as_continuation_monad.mdwn +++ b/list_monad_as_continuation_monad.mdwn @@ -112,7 +112,7 @@ will provide a connection with continuations. Recall that `List.map` takes a function and a list and returns the result to applying the function to the elements of the list: - List.map (fun i -> [i;i+1]) [1;2] ~~> [[1; 2]; [2; 3]] + List.map (fun i -> [i; i+1]) [1; 2] ~~> [[1; 2]; [2; 3]] and `List.concat` takes a list of lists and erases the embedded list boundaries: @@ -121,12 +121,12 @@ boundaries: And sure enough, - l_bind [1;2] (fun i -> [i, i+1]) ~~> [1; 2; 2; 3] + l_bind [1; 2] (fun i -> [i; i+1]) ~~> [1; 2; 2; 3] Now, why this unit, and why this bind? Well, ideally a unit should not throw away information, so we can rule out `fun x -> []` as an ideal unit. And units should not add more information than required, -so there's no obvious reason to prefer `fun x -> [x;x]`. In other +so there's no obvious reason to prefer `fun x -> [x; x]`. In other words, `fun x -> [x]` is a reasonable choice for a unit. As for bind, an `'a list` monadic object contains a lot of objects of @@ -136,7 +136,7 @@ thing we know for sure we can do with an object of type `'a` is apply the function of type `'a -> 'a list` to them. Once we've done so, we have a collection of lists, one for each of the `'a`'s. One possibility is that we could gather them all up in a list, so that -`bind' [1;2] (fun i -> [i;i]) ~~> [[1;1];[2;2]]`. But that restricts +`bind' [1; 2] (fun i -> [i; i]) ~~> [[1; 1]; [2; 2]]`. But that restricts the object returned by the second argument of `bind` to always be of type `'b list list`. We can eliminate that restriction by flattening the list of lists into a single list: this is @@ -198,7 +198,7 @@ Take an `'a` and return its v3-style singleton. No problem. Arriving at bind is a little more complicated, but exactly the same principles apply, you just have to be careful and systematic about it. - l'_bind (u : ('a,'b) list') (f : 'a -> ('c, 'd) list') : ('c, 'd) list' = ... + l'_bind (u : ('a, 'b) list') (f : 'a -> ('c, 'd) list') : ('c, 'd) list' = ... Unpacking the types gives: @@ -292,7 +292,7 @@ For future reference, we might make two eta-reductions to our formula, so that w Let's make some more tests: - l_bind [1;2] (fun i -> [i, i+1]) ~~> [1; 2; 2; 3] + l_bind [1; 2] (fun i -> [i; i+1]) ~~> [1; 2; 2; 3] l'_bind (fun f z -> f 1 (f 2 z)) (fun i -> fun f z -> f i (f (i+1) z)) ~~> @@ -357,6 +357,8 @@ This can be eta-reduced to: let l'_unit a = fun k -> k a +and: + let l'_bind u f = (* we mentioned three versions of this, the fully eta-expanded: *) fun k z -> u (fun a b -> f a k b) z