Prélude à l'après-midi d'un Stream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
module Control.Comonad where

{--

So, you've got monads down pat, and you use arrows where applicable, so ...
this comonad thing ... what's that?

First, the monad:

http://en.wikipedia.org/wiki/Monad_(category_theory)

Well, categorically, the monad is the triple (M, η, μ) where M is the monadic
type, η is the unit function (called 'return' in Haskell) and μ is the join
function (called 'join' in Haskell). For monads in Haskell (and in Java)
the bind operation (>>=) is favored over join, but a transformaion shows
working in one paradigm is easily translated into working in the other:

bind m f = join (fmap f m)

(well, for monads that are also functors, at any rate)

So the mathematicians may prefer the join function, and the coders the
bind operation, but they amount to the same work.

So, those are monads. We know them. We love them (or hate them).

They are there.

Now, comonads.

Comonads are the dual of monads. So whereas monads are the triple, described
above, comonads are the cotriple of the form (W, ε, δ) where W is the comonadic
type, ε is the extraction function, and δ is the duplication function.

Where monads lift base objects into the monadic domain, and once there, you're
'stuck' there, as it were, comonads extend the comonadic context over a
computation, and once you extract an object from a comonad, you can't
return it to there.

The dual of the the monadic bind operation is the comonadic extension (=>>).

And, like bind, extend can be expressed in terms of duplicate:

extend w f = fmap f (duplicate w).

I find comonads terrible useful when I'm operating on a particular
element of, say, a list, but I also need the context of the entire
list available at the same time.

Or, in Java particularly with its variability, when I'm certain of some
value, x, I wrap that in an Id comonad and proceed within the context
of that certainty from there. It eliminates so many downstream if (x != null)
assertions!

And, of course, I find that realized constants are comonadic.

http://blog.sigfpe.com/2008/06/categories-of-polynomials-and-comonadic.html
http://logicaltypes.blogspot.com/2012/11/coreader-x-costate-silver-bullet.html

*AHEM!*

Today's exercise: 

Write the comonad type-class and the instances for [a] such that:

extract [1,2,3] ~> 1
[1,2,3] =>> extract ~> [1,2,3]
[1,2,3] =>> id ~> [[1,2,3], [2,3], [3]]

and for Id a

 --}

data Id a = Id a
   deriving Show

{--

such that:

extract (Id "quux") ~> "quux"
Id "foo" =>> extract ~> Id "foo"
Id "bar" =>> id ~> Id (Id "bar")

(so, by example, it is demonstrated that 

duplicate w = w =>> id

and

id w = w =>> extract).

What are the signatures for extract, extend (and =>>), and duplicate?

What are their definitions for [a] and Id a?

Why are comonads so simple to declare, to define and to use?

Uh, never mind that last question: I just descended into comonadic rhetoric.

A solution is available at http://lpaste.net/edit/107662

 --}