Added presentation
Getty Ritter
10 years ago
1 | all: gcct.pdf | |
2 | ||
3 | gcct.pdf: gcct.tex | |
4 | pdflatex gcct.tex | |
5 | ||
6 | clean: | |
7 | rm -rf gcct.aux gcct.log gcct.pdf |
1 | \documentclass{scrartcl} | |
2 | \usepackage[letterpaper]{geometry} | |
3 | \usepackage{fullpage} | |
4 | \usepackage{cmbright} | |
5 | \usepackage[usenames,dvipsnames]{color} | |
6 | % \newcommand{\both}[2]{\begin{tabular}{ p{4in} p{4in} } #1 && #2 \\ \end{tabular}} | |
7 | \newcommand{\pos}[1]{\textcolor{BrickRed}{#1}} | |
8 | \newcommand{\postt}[1]{\textcolor{BrickRed}{\texttt{#1}}} | |
9 | \newcommand{\dual}[1]{\textcolor{NavyBlue}{#1}} | |
10 | \newcommand{\dualtt}[1]{\textcolor{NavyBlue}{\texttt{#1}}} | |
11 | \newenvironment{both} | |
12 | { \begin{tabular}{ p{3in} p{3in} } } | |
13 | { \\ \end{tabular} } | |
14 | \begin{document} | |
15 | \section{\pos{Data} and \dual{Codata}} | |
16 | ||
17 | \begin{both} | |
18 | \pos{Data} is defined by its \pos{introduction} rules. | |
19 | & \dual{Codata} is defined by its \dual{elimination} rules. | |
20 | \\ | |
21 | We can define a \pos{data} type with | |
22 | & We can define a \dual{codata} type with | |
23 | \\ | |
24 | \color{BrickRed} | |
25 | \begin{verbatim} | |
26 | data Either a b | |
27 | = Left a | |
28 | | Right b\end{verbatim} | |
29 | & | |
30 | \color{NavyBlue} | |
31 | \begin{verbatim} | |
32 | codata Both a b | |
33 | = first a | |
34 | & second b\end{verbatim} | |
35 | \\ | |
36 | This definition introduces two functions: | |
37 | & This definition introduces two functions: | |
38 | \\ | |
39 | \color{BrickRed} | |
40 | \begin{verbatim} | |
41 | Left : a -> Either a b | |
42 | Right : b -> Either a b\end{verbatim} | |
43 | & | |
44 | \color{NavyBlue} | |
45 | \begin{verbatim} | |
46 | first : Both a b -> a | |
47 | second : Both a b -> b\end{verbatim} | |
48 | \\ | |
49 | In order to \pos{destruct data} we have to use | |
50 | \pos{patterns} which let you match on \pos{constructors}. | |
51 | & In order to \dual{construct codata} we have to use | |
52 | \dual{copatterns} which let you match on \dual{destructors}. | |
53 | \\ | |
54 | \color{BrickRed} | |
55 | \begin{verbatim} | |
56 | (case e : Either a b of | |
57 | Left (x : a) -> (e1 : c) | |
58 | Right (y : b) -> (e2 : c)) : c\end{verbatim} | |
59 | & | |
60 | \color{NavyBlue} | |
61 | \begin{verbatim} | |
62 | (merge x : Both a b from | |
63 | first x <- e1 : a | |
64 | second x <- e2 : b) : Both a b\end{verbatim} | |
65 | \\ | |
66 | Here, \postt{e} represents the \pos{value being | |
67 | destructed}, and each branch represents a \pos{constructor | |
68 | with which it might have been constructed}. We are effectively | |
69 | \pos{dispatching on possible pasts} of | |
70 | \postt{e}. | |
71 | & Here, \dual{\texttt{x}} represents the \dual{value being | |
72 | constructed}, and each branch represents a \dual{destructor | |
73 | with which it might eventually be destructed}. We are effectively | |
74 | \dual{dispatching on possible futures} of | |
75 | \dualtt{x}. | |
76 | \\ | |
77 | \end{both} | |
78 | ||
79 | \section{Codata, Records, and Copatterns} | |
80 | \raggedright | |
81 | ||
82 | In the same way that named sums are a natural way to represent data, | |
83 | records are a natural way to represent codata. In lieu of the above | |
84 | syntax, one often sees codata represented as something more like | |
85 | ||
86 | {\color{NavyBlue} | |
87 | \begin{verbatim} | |
88 | record Both a b = { .first : a, .second : b } | |
89 | ||
90 | x : Both Int Bool | |
91 | x = { .first = 2, .second = true } | |
92 | ||
93 | x.first == 2, x.second == true | |
94 | \end{verbatim} | |
95 | } | |
96 | ||
97 | The \dualtt{merge} syntax is used here for conceptual | |
98 | symmetry with \postt{case}. Additionally, the use of | |
99 | copatterns is nicely dual with the extra expressivity that | |
100 | patterns offer. For example, we can use nested patterns with | |
101 | constructors of various types, as in this function which | |
102 | processes a list of \postt{Either Int Bool} values | |
103 | by summing the integers in the list until it reaches a | |
104 | \postt{false} value or the end of the list: | |
105 | ||
106 | {\color{BrickRed} | |
107 | \begin{verbatim} | |
108 | f : List (Either Int Bool) -> Int | |
109 | f lst = case lst of | |
110 | Cons (Left i) xs -> i + f xs | |
111 | Cons (Right b) xs -> if b then f xs else 0 | |
112 | Nil -> 0 | |
113 | \end{verbatim} | |
114 | } | |
115 | ||
116 | Similarly, we can define an infinite stream of pairs using | |
117 | nested copatterns as so: | |
118 | ||
119 | {\color{NavyBlue} | |
120 | \begin{verbatim} | |
121 | s : Int -> Stream (Both Int Bool) | |
122 | s n = merge x from | |
123 | first (head x) <- n | |
124 | second (head x) <- n > 0 | |
125 | tail x <- x | |
126 | \end{verbatim} | |
127 | } | |
128 | ||
129 | Copatterns are also practically expressive, as in this concise | |
130 | and readable definition of the fibonacci numbers in terms of | |
131 | the \dualtt{merge} expression: | |
132 | ||
133 | {\color{NavyBlue} | |
134 | \begin{verbatim} | |
135 | codata Stream a | |
136 | = head a | |
137 | & tail (Stream a) | |
138 | ||
139 | zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c | |
140 | zipWith f s1 s2 = merge x from | |
141 | head x <- f (head s1) (head s2) | |
142 | tail x <- zipWith f (tail s1) (tail s2) | |
143 | ||
144 | fibs : Stream Int | |
145 | fibs = merge x from | |
146 | head x <- 0 | |
147 | head (tail x) <- 1 | |
148 | tail (tail x) <- zipWith (+) x (tail x) | |
149 | \end{verbatim} | |
150 | } | |
151 | ||
152 | \section{Generalizing \dual{Co}data} | |
153 | ||
154 | \begin{both} | |
155 | A \pos{Generalized Algebraic Data Type} adds extra | |
156 | expressivity to \pos{data} types by allowing extra | |
157 | restrictions on the value being \pos{constructed}. | |
158 | & A \dual{Generalized Coalgebraic Codata Type} adds extra | |
159 | expressivity to \dual{codata} types by allowing extra | |
160 | restrictions on the value being \dual{destructed}. | |
161 | \\ | |
162 | \color{BrickRed} | |
163 | \begin{verbatim} | |
164 | data Join a where | |
165 | Unit : Int -> Join Int | |
166 | Join : (Join a, Join a) -> | |
167 | Join (a, a)\end{verbatim} | |
168 | & | |
169 | \color{NavyBlue} | |
170 | \begin{verbatim} | |
171 | codata Split a where | |
172 | unit : Split Int -> Int | |
173 | split : Split (a, a) -> | |
174 | (Split a, Split a)\end{verbatim} | |
175 | \\ | |
176 | This definition precludes the use of any value of the | |
177 | type \pos{Join(Int, Bool)} because there is no way | |
178 | to \pos{construct} a value of this type---we can only | |
179 | \pos{construct} values with pairs of the same type, | |
180 | or containing an \texttt{Int}. | |
181 | & | |
182 | This definition precludes the use of any value of the | |
183 | type \dual{Split(Int, Bool)} because there is no way | |
184 | to \dual{destruct} a value of this type---we can only | |
185 | \dual{destruct} values with pairs of the same type, | |
186 | or containing an \texttt{Int}. | |
187 | \\ | |
188 | This gives us extra type information to omit nonsensical | |
189 | branches in \postt{case}, as well. The following code | |
190 | matches over a value of type \postt{Join Int}, and as | |
191 | such only has an arm for the \pos{constructor} | |
192 | \postt{Unit}---because it is the only \pos{constructor} | |
193 | which can \pos{create} a value of that type! | |
194 | & | |
195 | This gives us extra type information to omit nonsensical | |
196 | branches in \dualtt{merge}, as well. The following code | |
197 | matches over a value of type \dualtt{Split Int}, and as | |
198 | such only has an arm for the \dual{destructor} | |
199 | \dualtt{unit}---because it is the only \dual{destructor} | |
200 | which can \dual{destruct} a value of that type! | |
201 | \\ | |
202 | \color{BrickRed} | |
203 | \begin{verbatim} | |
204 | f : Join Int -> Int | |
205 | f x = case x of | |
206 | Unit n -> n\end{verbatim} | |
207 | & | |
208 | \color{NavyBlue} | |
209 | \begin{verbatim} | |
210 | g : Int -> Split Int | |
211 | g n = merge x from | |
212 | unit x <- n\end{verbatim} | |
213 | \\ | |
214 | We can \pos{construct} a value of type \postt{Join Int} | |
215 | in conjunction with using \postt{f} like so: | |
216 | & We can \dual{destruct} a value of type \dualtt{Split Int} | |
217 | in conjunction with using \dualtt{g} like so: | |
218 | \\ | |
219 | \color{BrickRed} | |
220 | \begin{verbatim} | |
221 | let y : Join Int | |
222 | y = Unit 5 | |
223 | in | |
224 | f y\end{verbatim} | |
225 | & | |
226 | \color{NavyBlue} | |
227 | \begin{verbatim} | |
228 | let y : Split Int | |
229 | y = g 5 | |
230 | in | |
231 | unit y\end{verbatim} | |
232 | \\ | |
233 | \end{both} | |
234 | ||
235 | \section{Focus on GCCTs} | |
236 | ||
237 | To dispense with the dual presentation: a simple, high-level, handwavey | |
238 | description of GCCTs is that they are \textit{records whose available | |
239 | projections may be restricted by | |
240 | the type of the record}. Like GADTs, they can introduce and use extra | |
241 | typing information. For example, consider the following GCCT and its | |
242 | instantiations: | |
243 | ||
244 | {\color{NavyBlue} | |
245 | \begin{verbatim} | |
246 | codata Wrapper a where | |
247 | contents : Wrapper a -> a | |
248 | isZero : Wrapper Int -> Bool | |
249 | ||
250 | mkStringW : String -> Wrapper String | |
251 | mkStringW x = merge r from | |
252 | contents r <- x | |
253 | ||
254 | mkIntW : Int -> Wrapper Int | |
255 | mkIntW x = merge r from | |
256 | contents r <- x | |
257 | isZero r <- x == 0 | |
258 | \end{verbatim} | |
259 | } | |
260 | ||
261 | A \dualtt{Wrapper} value is a wrapper over some other value, which can always be | |
262 | extracted using the projection \dualtt{contents}. However, if the value | |
263 | contained in the ``record'' is an \texttt{Int}, we have a second projection | |
264 | available to us: we can also use \dualtt{isZero} to project out a boolean. | |
265 | ||
266 | In fact, because of the type machinery afforded us by GCCTs, we can | |
267 | actually collapse both \dualtt{mkStringW} and \dualtt{mkIntW} into a | |
268 | single function, \dualtt{mkWrapper}, like so: | |
269 | ||
270 | {\color{NavyBlue} | |
271 | \begin{verbatim} | |
272 | mkWrapper : a -> Wrapper a | |
273 | mkWrapper x = merge r from | |
274 | contents r <- x | |
275 | isZero r <- x == 0 | |
276 | \end{verbatim} | |
277 | } | |
278 | ||
279 | The reason this is valid is that, like with GADTs, copattern matching on | |
280 | \dualtt{isZero} gives us extra type information about \dualtt{x}, and so | |
281 | will only be a valid branch when \dualtt{mkWrapper} is called with a | |
282 | value of type \dualtt{Int}; otherwise it is merely a redundant branch | |
283 | and is ignored. | |
284 | ||
285 | \subsection{Finite State Automata} | |
286 | ||
287 | We can use these in a few interesting ways: for example, consider the situation | |
288 | in which we have a finite state automaton for recognizing a language. For | |
289 | simplicity's sake, we'll restrict the states to \texttt{A}, \texttt{B}, and | |
290 | \texttt{C}, and allow the following valid transitions: | |
291 | ||
292 | \begin{verbatim} | |
293 | A -> B,C | |
294 | B -> C | |
295 | C -> A | |
296 | \end{verbatim} | |
297 | ||
298 | We want a data structure which represents the transitions available. We can do | |
299 | this, even in a strongly normalizing setting, by representing the FSA using | |
300 | a piece of infinite codata with projections for each state transition: | |
301 | ||
302 | {\color{NavyBlue} | |
303 | \begin{verbatim} | |
304 | data State = A | B | C | |
305 | codata NFA (a : State) where | |
306 | aToB : NFA A -> NFA B | |
307 | aToC : NFA A -> NFA C | |
308 | bToC : NFA B -> NFA C | |
309 | cToA : NFA C -> NFA A | |
310 | \end{verbatim} | |
311 | } | |
312 | ||
313 | This means that the following expressions (which use \texttt{.} to mean | |
314 | function composition) type-check as they represent valid | |
315 | state transitions | |
316 | ||
317 | \begin{verbatim} | |
318 | aState : NFA A | |
319 | aToB aState : NFA B | |
320 | (bToC . aToB) aState : NFA C | |
321 | (cToA . bToC . aToB) aState : NFA A | |
322 | \end{verbatim} | |
323 | ||
324 | whereas the following do not | |
325 | ||
326 | \begin{verbatim} | |
327 | bToC aState -- cannot unify `NFA A` with `NFA B` | |
328 | (aToC . aToB) aState -- cannot unify `NFA B` with `NFA A` | |
329 | \end{verbatim} | |
330 | ||
331 | We can construct an initial \dualtt{aState} value using the following | |
332 | \dualtt{merge} expression, using an extra \texttt{let}-binding to improve | |
333 | the sharing in this structure: | |
334 | ||
335 | {\color{NavyBlue} | |
336 | \begin{verbatim} | |
337 | aState : NFA A | |
338 | aState = | |
339 | merge as from | |
340 | let cState = (merge cs from cToA cs <- as) in | |
341 | aToC as <- cState | |
342 | aToB as <- (merge bs from bToC bs <- cState) | |
343 | \end{verbatim} | |
344 | } | |
345 | ||
346 | or much more concisely by using nested copatterns: | |
347 | ||
348 | {\color{NavyBlue} | |
349 | \begin{verbatim} | |
350 | aState : NFA A | |
351 | aState = merge as from | |
352 | cToA (aToC as) <- as | |
353 | cToA (bToC (aToB as)) <- as | |
354 | \end{verbatim} | |
355 | } | |
356 | ||
357 | We can make this more interesting (and more useful) by introducing an extra | |
358 | operation: suppose we're using this to recognize a language equivalent to the | |
359 | regular expression \texttt{/a(b?ca)*/}, and we want to be able to extract | |
360 | the string we've matched, but \textit{only} in the accept state | |
361 | \texttt{A}. We can change the codata definition to have such an accessor: | |
362 | ||
363 | {\color{NavyBlue} | |
364 | \begin{verbatim} | |
365 | codata NFA (a : State) where | |
366 | aToB : NFA A -> NFA B | |
367 | aToC : NFA A -> NFA C | |
368 | bToC : NFA B -> NFA C | |
369 | cToA : NFA C -> NFA A | |
370 | matchedString : NFA A -> String | |
371 | \end{verbatim} | |
372 | } | |
373 | ||
374 | and change the construction of the NFA to this: | |
375 | ||
376 | {\color{NavyBlue} | |
377 | \begin{verbatim} | |
378 | aState : NFA A | |
379 | aState = | |
380 | let f str = | |
381 | merge as from | |
382 | matchedString as <- str | |
383 | cToA (aToC as) <- f (str ++ "ca") | |
384 | cToA (bToC (aToB as)) <- f (str ++ "bca") | |
385 | in f "a" | |
386 | \end{verbatim} | |
387 | } | |
388 | ||
389 | Consequently the following holds true: | |
390 | ||
391 | \begin{verbatim} | |
392 | (matchedString . cToA . atoC . cToA . bToC . aToB) aState == "abcaca" | |
393 | \end{verbatim} | |
394 | ||
395 | whereas the following does not type-check: | |
396 | ||
397 | \begin{verbatim} | |
398 | (matchedString . bToC . aToB) aState | |
399 | \end{verbatim} | |
400 | ||
401 | \subsection{A Forth-Like Embedded Language} | |
402 | ||
403 | Consider the following codata type: | |
404 | ||
405 | {\color{NavyBlue} | |
406 | \begin{verbatim} | |
407 | codata Forth a where | |
408 | push : Forth a -> b -> Forth (b, a) | |
409 | get : Forth (a, b) -> a | |
410 | drop : Forth (a, b) -> Forth b | |
411 | swap : Forth (a, (b, c)) -> Forth (b, (a, c)) | |
412 | app : Forth (a, (b, c)) -> (a -> b -> d) -> Forth (d, c) | |
413 | \end{verbatim} | |
414 | } | |
415 | ||
416 | This corresponds to a small embedded Forth-like sublanguage, in which | |
417 | a value of type \dualtt{Forth} corresponds to the state of a stack whose | |
418 | type is given by the type parameter. This means that not only is it an | |
419 | embedded Forth-like language, it is a well-typed language that can take | |
420 | arbitrary values in the host language and manipulate them on the stack. | |
421 | Assuming the use of the operator \texttt{x \# f = f x}, we can write a | |
422 | well-typed subprogram | |
423 | ||
424 | {\color{NavyBlue} | |
425 | \begin{verbatim} | |
426 | initialState # push 5 | |
427 | # push 2 | |
428 | # push 3 | |
429 | # swap | |
430 | # drop | |
431 | # add | |
432 | # get | |
433 | \end{verbatim} | |
434 | } | |
435 | ||
436 | and also reject this ill-typed subprogram, where \texttt{add} requires | |
437 | two integers but is given a stack with a boolean on top | |
438 | ||
439 | {\color{NavyBlue} | |
440 | \begin{verbatim} | |
441 | initialState # push 5 # push true # add # get | |
442 | \end{verbatim} | |
443 | } | |
444 | ||
445 | but also this one, in which \texttt{add} is only given a single argument | |
446 | ||
447 | {\color{NavyBlue} | |
448 | \begin{verbatim} | |
449 | initialState # push 5 # add # get | |
450 | \end{verbatim} | |
451 | } | |
452 | ||
453 | We have to create a helper function in order to create a value of this | |
454 | type, which is the helper function \dualtt{push'}: | |
455 | ||
456 | {\color{NavyBlue} | |
457 | \begin{verbatim} | |
458 | doPush : Forth a -> b -> Forth (b, a) | |
459 | doPush s x = merge s' from | |
460 | push s' <- doPush s' | |
461 | get s' <- x | |
462 | drop s' <- s | |
463 | swap s' <- push (get s) (push x (drop s)) | |
464 | app s' <- | |
465 | let doApp f = push (f x (get s)) (drop s) | |
466 | in doApp | |
467 | \end{verbatim} | |
468 | } | |
469 | ||
470 | And then we can create an actual value of type \dualtt{Forth ()}: | |
471 | ||
472 | {\color{NavyBlue} | |
473 | \begin{verbatim} | |
474 | initialState : Forth () | |
475 | initialState = merge s' | |
476 | push s' <- doPush s' | |
477 | \end{verbatim} | |
478 | } | |
479 | ||
480 | \end{document} |
1 | all: gcct.pdf | |
2 | ||
3 | gcct.pdf: gcct.tex | |
4 | pdflatex gcct.tex | |
5 | ||
6 | clean: | |
7 | rm -rf gcct.aux gcct.log gcct.pdf |
1 | \documentclass{scrartcl} | |
2 | \usepackage[letterpaper]{geometry} | |
3 | \usepackage{fullpage} | |
4 | \usepackage{cmbright} | |
5 | \usepackage[usenames,dvipsnames]{color} | |
6 | % \newcommand{\both}[2]{\begin{tabular}{ p{4in} p{4in} } #1 && #2 \\ \end{tabular}} | |
7 | \newcommand{\pos}[1]{\textcolor{BrickRed}{#1}} | |
8 | \newcommand{\postt}[1]{\textcolor{BrickRed}{\texttt{#1}}} | |
9 | \newcommand{\dual}[1]{\textcolor{NavyBlue}{#1}} | |
10 | \newcommand{\dualtt}[1]{\textcolor{NavyBlue}{\texttt{#1}}} | |
11 | \newenvironment{both} | |
12 | { \begin{tabular}{ p{3in} p{3in} } } | |
13 | { \\ \end{tabular} } | |
14 | \begin{document} | |
15 | \section{\pos{Data} and \dual{Codata}} | |
16 | ||
17 | \begin{both} | |
18 | \pos{Data} is defined by its \pos{introduction} rules. | |
19 | & \dual{Codata} is defined by its \dual{elimination} rules. | |
20 | \\ | |
21 | We can define a \pos{data} type with | |
22 | & We can define a \dual{codata} type with | |
23 | \\ | |
24 | \color{BrickRed} | |
25 | \begin{verbatim} | |
26 | data Either a b | |
27 | = Left a | |
28 | | Right b\end{verbatim} | |
29 | & | |
30 | \color{NavyBlue} | |
31 | \begin{verbatim} | |
32 | codata Both a b | |
33 | = first a | |
34 | & second b\end{verbatim} | |
35 | \\ | |
36 | This definition introduces two functions: | |
37 | & This definition introduces two functions: | |
38 | \\ | |
39 | \color{BrickRed} | |
40 | \begin{verbatim} | |
41 | Left : a -> Either a b | |
42 | Right : b -> Either a b\end{verbatim} | |
43 | & | |
44 | \color{NavyBlue} | |
45 | \begin{verbatim} | |
46 | first : Both a b -> a | |
47 | second : Both a b -> b\end{verbatim} | |
48 | \\ | |
49 | In order to \pos{destruct data} we have to use | |
50 | \pos{patterns} which let you match on \pos{constructors}. | |
51 | & In order to \dual{construct codata} we have to use | |
52 | \dual{copatterns} which let you match on \dual{destructors}. | |
53 | \\ | |
54 | \color{BrickRed} | |
55 | \begin{verbatim} | |
56 | (case e : Either a b of | |
57 | Left (x : a) -> (e1 : c) | |
58 | Right (y : b) -> (e2 : c)) : c\end{verbatim} | |
59 | & | |
60 | \color{NavyBlue} | |
61 | \begin{verbatim} | |
62 | (merge x : Both a b from | |
63 | first x <- e1 : a | |
64 | second x <- e2 : b) : Both a b\end{verbatim} | |
65 | \\ | |
66 | Here, \postt{e} represents the \pos{value being | |
67 | destructed}, and each branch represents a \pos{constructor | |
68 | with which it might have been constructed}. We are effectively | |
69 | \pos{dispatching on possible pasts} of | |
70 | \postt{e}. | |
71 | & Here, \dual{\texttt{x}} represents the \dual{value being | |
72 | constructed}, and each branch represents a \dual{destructor | |
73 | with which it might eventually be destructed}. We are effectively | |
74 | \dual{dispatching on possible futures} of | |
75 | \dualtt{x}. | |
76 | \\ | |
77 | \end{both} | |
78 | ||
79 | \section{Codata, Records, and Copatterns} | |
80 | \raggedright | |
81 | ||
82 | In the same way that named sums are a natural way to represent data, | |
83 | records are a natural way to represent codata. In lieu of the above | |
84 | syntax, one often sees codata represented as something more like | |
85 | ||
86 | {\color{NavyBlue} | |
87 | \begin{verbatim} | |
88 | record Both a b = { .first : a, .second : b } | |
89 | ||
90 | x : Both Int Bool | |
91 | x = { .first = 2, .second = true } | |
92 | ||
93 | x.first == 2, x.second == true | |
94 | \end{verbatim} | |
95 | } | |
96 | ||
97 | The \dualtt{merge} syntax is used here for conceptual | |
98 | symmetry with \postt{case}. Additionally, the use of | |
99 | copatterns is nicely dual with the extra expressivity that | |
100 | patterns offer. For example, we can use nested patterns with | |
101 | constructors of various types, as in this function which | |
102 | processes a list of \postt{Either Int Bool} values | |
103 | by summing the integers in the list until it reaches a | |
104 | \postt{false} value or the end of the list: | |
105 | ||
106 | {\color{BrickRed} | |
107 | \begin{verbatim} | |
108 | f : List (Either Int Bool) -> Int | |
109 | f lst = case lst of | |
110 | Cons (Left i) xs -> i + f xs | |
111 | Cons (Right b) xs -> if b then f xs else 0 | |
112 | Nil -> 0 | |
113 | \end{verbatim} | |
114 | } | |
115 | ||
116 | Similarly, we can define an infinite stream of pairs using | |
117 | nested copatterns as so: | |
118 | ||
119 | {\color{NavyBlue} | |
120 | \begin{verbatim} | |
121 | s : Int -> Stream (Both Int Bool) | |
122 | s n = merge x from | |
123 | first (head x) <- n | |
124 | second (head x) <- n > 0 | |
125 | tail x <- x | |
126 | \end{verbatim} | |
127 | } | |
128 | ||
129 | Copatterns are also practically expressive, as in this concise | |
130 | and readable definition of the fibonacci numbers in terms of | |
131 | the \dualtt{merge} expression: | |
132 | ||
133 | {\color{NavyBlue} | |
134 | \begin{verbatim} | |
135 | codata Stream a | |
136 | = head a | |
137 | & tail (Stream a) | |
138 | ||
139 | zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c | |
140 | zipWith f s1 s2 = merge x from | |
141 | head x <- f (head s1) (head s2) | |
142 | tail x <- zipWith f (tail s1) (tail s2) | |
143 | ||
144 | fibs : Stream Int | |
145 | fibs = merge x from | |
146 | head x <- 0 | |
147 | head (tail x) <- 1 | |
148 | tail (tail x) <- zipWith (+) x (tail x) | |
149 | \end{verbatim} | |
150 | } | |
151 | ||
152 | \section{Generalizing \dual{Co}data} | |
153 | ||
154 | \begin{both} | |
155 | A \pos{Generalized Algebraic Data Type} adds extra | |
156 | expressivity to \pos{data} types by allowing extra | |
157 | restrictions on the value being \pos{constructed}. | |
158 | & A \dual{Generalized Coalgebraic Codata Type} adds extra | |
159 | expressivity to \dual{codata} types by allowing extra | |
160 | restrictions on the value being \dual{destructed}. | |
161 | \\ | |
162 | \color{BrickRed} | |
163 | \begin{verbatim} | |
164 | data Join a where | |
165 | Unit : Int -> Join Int | |
166 | Join : (Join a, Join a) -> | |
167 | Join (a, a)\end{verbatim} | |
168 | & | |
169 | \color{NavyBlue} | |
170 | \begin{verbatim} | |
171 | codata Split a where | |
172 | unit : Split Int -> Int | |
173 | split : Split (a, a) -> | |
174 | (Split a, Split a)\end{verbatim} | |
175 | \\ | |
176 | This definition precludes the use of any value of the | |
177 | type \pos{Join(Int, Bool)} because there is no way | |
178 | to \pos{construct} a value of this type---we can only | |
179 | \pos{construct} values with pairs of the same type, | |
180 | or containing an \texttt{Int}. | |
181 | & | |
182 | This definition precludes the use of any value of the | |
183 | type \dual{Split(Int, Bool)} because there is no way | |
184 | to \dual{destruct} a value of this type---we can only | |
185 | \dual{destruct} values with pairs of the same type, | |
186 | or containing an \texttt{Int}. | |
187 | \\ | |
188 | This gives us extra type information to omit nonsensical | |
189 | branches in \postt{case}, as well. The following code | |
190 | matches over a value of type \postt{Join Int}, and as | |
191 | such only has an arm for the \pos{constructor} | |
192 | \postt{Unit}---because it is the only \pos{constructor} | |
193 | which can \pos{create} a value of that type! | |
194 | & | |
195 | This gives us extra type information to omit nonsensical | |
196 | branches in \dualtt{merge}, as well. The following code | |
197 | matches over a value of type \dualtt{Split Int}, and as | |
198 | such only has an arm for the \dual{destructor} | |
199 | \dualtt{unit}---because it is the only \dual{destructor} | |
200 | which can \dual{destruct} a value of that type! | |
201 | \\ | |
202 | \color{BrickRed} | |
203 | \begin{verbatim} | |
204 | f : Join Int -> Int | |
205 | f x = case x of | |
206 | Unit n -> n\end{verbatim} | |
207 | & | |
208 | \color{NavyBlue} | |
209 | \begin{verbatim} | |
210 | g : Int -> Split Int | |
211 | g n = merge x from | |
212 | unit x <- n\end{verbatim} | |
213 | \\ | |
214 | We can \pos{construct} a value of type \postt{Join Int} | |
215 | in conjunction with using \postt{f} like so: | |
216 | & We can \dual{destruct} a value of type \dualtt{Split Int} | |
217 | in conjunction with using \dualtt{g} like so: | |
218 | \\ | |
219 | \color{BrickRed} | |
220 | \begin{verbatim} | |
221 | let y : Join Int | |
222 | y = Unit 5 | |
223 | in | |
224 | f y\end{verbatim} | |
225 | & | |
226 | \color{NavyBlue} | |
227 | \begin{verbatim} | |
228 | let y : Split Int | |
229 | y = g 5 | |
230 | in | |
231 | unit y\end{verbatim} | |
232 | \\ | |
233 | \end{both} | |
234 | ||
235 | \section{Focus on GCCTs} | |
236 | ||
237 | To dispense with the dual presentation: a simple, high-level, handwavey | |
238 | description of GCCTs is that they are \textit{records whose available | |
239 | projections may be restricted by | |
240 | the type of the record}. Like GADTs, they can introduce and use extra | |
241 | typing information. For example, consider the following GCCT and its | |
242 | instantiations: | |
243 | ||
244 | {\color{NavyBlue} | |
245 | \begin{verbatim} | |
246 | codata Wrapper a where | |
247 | contents : Wrapper a -> a | |
248 | isZero : Wrapper Int -> Bool | |
249 | ||
250 | mkStringW : String -> Wrapper String | |
251 | mkStringW x = merge r from | |
252 | contents r <- x | |
253 | ||
254 | mkIntW : Int -> Wrapper Int | |
255 | mkIntW x = merge r from | |
256 | contents r <- x | |
257 | isZero r <- x == 0 | |
258 | \end{verbatim} | |
259 | } | |
260 | ||
261 | A \dualtt{Wrapper} value is a wrapper over some other value, which can always be | |
262 | extracted using the projection \dualtt{contents}. However, if the value | |
263 | contained in the ``record'' is an \texttt{Int}, we have a second projection | |
264 | available to us: we can also use \dualtt{isZero} to project out a boolean. | |
265 | ||
266 | In fact, because of the type machinery afforded us by GCCTs, we can | |
267 | actually collapse both \dualtt{mkStringW} and \dualtt{mkIntW} into a | |
268 | single function, \dualtt{mkWrapper}, like so: | |
269 | ||
270 | {\color{NavyBlue} | |
271 | \begin{verbatim} | |
272 | mkWrapper : a -> Wrapper a | |
273 | mkWrapper x = merge r from | |
274 | contents r <- x | |
275 | isZero r <- x == 0 | |
276 | \end{verbatim} | |
277 | } | |
278 | ||
279 | The reason this is valid is that, like with GADTs, copattern matching on | |
280 | \dualtt{isZero} gives us extra type information about \dualtt{x}, and so | |
281 | will only be a valid branch when \dualtt{mkWrapper} is called with a | |
282 | value of type \dualtt{Int}; otherwise it is merely a redundant branch | |
283 | and is ignored. | |
284 | ||
285 | \subsection{Finite State Automata} | |
286 | ||
287 | We can use these in a few interesting ways: for example, consider the situation | |
288 | in which we have a finite state automaton for recognizing a language. For | |
289 | simplicity's sake, we'll restrict the states to \texttt{A}, \texttt{B}, and | |
290 | \texttt{C}, and allow the following valid transitions: | |
291 | ||
292 | \begin{verbatim} | |
293 | A -> B,C | |
294 | B -> C | |
295 | C -> A | |
296 | \end{verbatim} | |
297 | ||
298 | We want a data structure which represents the transitions available. We can do | |
299 | this, even in a strongly normalizing setting, by representing the FSA using | |
300 | a piece of infinite codata with projections for each state transition: | |
301 | ||
302 | {\color{NavyBlue} | |
303 | \begin{verbatim} | |
304 | data State = A | B | C | |
305 | codata NFA (a : State) where | |
306 | aToB : NFA A -> NFA B | |
307 | aToC : NFA A -> NFA C | |
308 | bToC : NFA B -> NFA C | |
309 | cToA : NFA C -> NFA A | |
310 | \end{verbatim} | |
311 | } | |
312 | ||
313 | This means that the following expressions (which use \texttt{.} to mean | |
314 | function composition) type-check as they represent valid | |
315 | state transitions | |
316 | ||
317 | \begin{verbatim} | |
318 | aState : NFA A | |
319 | aToB aState : NFA B | |
320 | (bToC . aToB) aState : NFA C | |
321 | (cToA . bToC . aToB) aState : NFA A | |
322 | \end{verbatim} | |
323 | ||
324 | whereas the following do not | |
325 | ||
326 | \begin{verbatim} | |
327 | bToC aState -- cannot unify `NFA A` with `NFA B` | |
328 | (aToC . aToB) aState -- cannot unify `NFA B` with `NFA A` | |
329 | \end{verbatim} | |
330 | ||
331 | We can construct an initial \dualtt{aState} value using the following | |
332 | \dualtt{merge} expression, using an extra \texttt{let}-binding to improve | |
333 | the sharing in this structure: | |
334 | ||
335 | {\color{NavyBlue} | |
336 | \begin{verbatim} | |
337 | aState : NFA A | |
338 | aState = | |
339 | merge as from | |
340 | let cState = (merge cs from cToA cs <- as) in | |
341 | aToC as <- cState | |
342 | aToB as <- (merge bs from bToC bs <- cState) | |
343 | \end{verbatim} | |
344 | } | |
345 | ||
346 | or much more concisely by using nested copatterns: | |
347 | ||
348 | {\color{NavyBlue} | |
349 | \begin{verbatim} | |
350 | aState : NFA A | |
351 | aState = merge as from | |
352 | cToA (aToC as) <- as | |
353 | cToA (bToC (aToB as)) <- as | |
354 | \end{verbatim} | |
355 | } | |
356 | ||
357 | We can make this more interesting (and more useful) by introducing an extra | |
358 | operation: suppose we're using this to recognize a language equivalent to the | |
359 | regular expression \texttt{/a(b?ca)*/}, and we want to be able to extract | |
360 | the string we've matched, but \textit{only} in the accept state | |
361 | \texttt{A}. We can change the codata definition to have such an accessor: | |
362 | ||
363 | {\color{NavyBlue} | |
364 | \begin{verbatim} | |
365 | codata NFA (a : State) where | |
366 | aToB : NFA A -> NFA B | |
367 | aToC : NFA A -> NFA C | |
368 | bToC : NFA B -> NFA C | |
369 | cToA : NFA C -> NFA A | |
370 | matchedString : NFA A -> String | |
371 | \end{verbatim} | |
372 | } | |
373 | ||
374 | and change the construction of the NFA to this: | |
375 | ||
376 | {\color{NavyBlue} | |
377 | \begin{verbatim} | |
378 | aState : NFA A | |
379 | aState = | |
380 | let f str = | |
381 | merge | |
382 | matchedString _ <- str | |
383 | cToA (aToC _) <- f (str ++ "ca") | |
384 | cToA (bToC (aToB _)) <- f (str ++ "bca") | |
385 | in f "a" | |
386 | \end{verbatim} | |
387 | } | |
388 | ||
389 | Consequently the following holds true: | |
390 | ||
391 | \begin{verbatim} | |
392 | (matchedString . cToA . atoC . cToA . bToC . aToB) aState == "abcaca" | |
393 | \end{verbatim} | |
394 | ||
395 | whereas the following does not type-check: | |
396 | ||
397 | \begin{verbatim} | |
398 | (matchedString . bToC . aToB) aState | |
399 | \end{verbatim} | |
400 | ||
401 | \subsection{A Forth-Like Embedded Language} | |
402 | ||
403 | Consider the following codata type: | |
404 | ||
405 | {\color{NavyBlue} | |
406 | \begin{verbatim} | |
407 | codata Forth a where | |
408 | push : Forth a -> b -> Forth (b, a) | |
409 | get : Forth (a, b) -> a | |
410 | drop : Forth (a, b) -> Forth b | |
411 | swap : Forth (a, (b, c)) -> Forth (b, (a, c)) | |
412 | app : Forth (a, (b, c)) -> (a -> b -> d) -> Forth (d, c) | |
413 | \end{verbatim} | |
414 | } | |
415 | ||
416 | This corresponds to a small embedded Forth-like sublanguage, in which | |
417 | a value of type \dualtt{Forth} corresponds to the state of a stack whose | |
418 | type is given by the type parameter. This means that not only is it an | |
419 | embedded Forth-like language, it is a well-typed language that can take | |
420 | arbitrary values in the host language and manipulate them on the stack. | |
421 | Assuming the use of the operator \texttt{x \# f = f x}, we can write a | |
422 | well-typed subprogram | |
423 | ||
424 | {\color{NavyBlue} | |
425 | \begin{verbatim} | |
426 | initialState # push 5 | |
427 | # push 2 | |
428 | # push 3 | |
429 | # swap | |
430 | # drop | |
431 | # add | |
432 | # get | |
433 | \end{verbatim} | |
434 | } | |
435 | ||
436 | and also reject this ill-typed subprogram, where \texttt{add} requires | |
437 | two integers but is given a stack with a boolean on top | |
438 | ||
439 | {\color{NavyBlue} | |
440 | \begin{verbatim} | |
441 | initialState # push 5 # push true # add # get | |
442 | \end{verbatim} | |
443 | } | |
444 | ||
445 | but also this one, in which \texttt{add} is only given a single argument | |
446 | ||
447 | {\color{NavyBlue} | |
448 | \begin{verbatim} | |
449 | initialState # push 5 # add # get | |
450 | \end{verbatim} | |
451 | } | |
452 | ||
453 | We have to create a helper function in order to create a value of this | |
454 | type, which is the helper function \dualtt{push'}: | |
455 | ||
456 | {\color{NavyBlue} | |
457 | \begin{verbatim} | |
458 | doPush : Forth a -> b -> Forth (b, a) | |
459 | doPush s x = merge s' from | |
460 | push s' <- doPush s' | |
461 | get s' <- x | |
462 | drop s' <- s | |
463 | swap s' <- push (get s) (push x (drop s)) | |
464 | app s' <- | |
465 | let doApp f = push (f x (get s)) (drop s) | |
466 | in doApp | |
467 | \end{verbatim} | |
468 | } | |
469 | ||
470 | And then we can create an actual value of type \dualtt{Forth ()}: | |
471 | ||
472 | {\color{NavyBlue} | |
473 | \begin{verbatim} | |
474 | initialState : Forth () | |
475 | initialState = merge s' | |
476 | push s' <- doPush s' | |
477 | \end{verbatim} | |
478 | } | |
479 | ||
480 | \subsection{The Co\"operational Comonad} | |
481 | ||
482 | Two convenient minimal definitions of a \texttt{Monad} are in terms | |
483 | of \texttt{return} and either \texttt{join} and \texttt{fmap} or | |
484 | \texttt{bind}: | |
485 | ||
486 | \begin{verbatim} | |
487 | class Monad m where | |
488 | return : a -> m a | |
489 | join : m (m a) -> m a | |
490 | map : (a -> b) -> m a -> m b | |
491 | ||
492 | bind : Monad m => (a -> m b) -> m a -> m b | |
493 | bind f x = join (map f x) | |
494 | \end{verbatim} | |
495 | ||
496 | \begin{verbatim} | |
497 | class Monad m where | |
498 | return : a -> m a | |
499 | bind : (a -> m b) -> m a -> m b | |
500 | ||
501 | join : Monad m => m (m a) -> m a | |
502 | join = map return | |
503 | ||
504 | map : (a -> b) -> m a -> m b | |
505 | map f x = bind (return . f) x | |
506 | \end{verbatim} | |
507 | ||
508 | This implies two ways of constructing a data structure that is | |
509 | trivially a monad. The first is the traditional construction of | |
510 | a free monad, which has two constructors which correspond to | |
511 | \texttt{return} and \texttt{Join}: | |
512 | ||
513 | \begin{verbatim} | |
514 | data Free : (* -> *) -> * -> * | |
515 | = Pure a | |
516 | | Join (f (Free f a)) | |
517 | \end{verbatim} | |
518 | ||
519 | In order to be a \texttt{Monad}, then the first parameter given | |
520 | to \texttt{Free} must be a \texttt{Functor}, so that we get the | |
521 | ability to \texttt{map} as well: | |
522 | ||
523 | \begin{verbatim} | |
524 | instance Functor f => Monad (Free f) where | |
525 | return = Pure | |
526 | ||
527 | map f (Pure x) = Pure (f x) | |
528 | map f (Join xs) = Join (fmap f xs) | |
529 | ||
530 | join (Pure x) = x | |
531 | join (Join xs) = Join (fmap join xs) | |
532 | \end{verbatim} | |
533 | ||
534 | However, we could also write a data structure which is trivially | |
535 | a monad whose type corresponds to \texttt{return} and \texttt{bind}, | |
536 | in which case we needn't have a functor constraint on the type | |
537 | parameter. For this, we need GADTs: | |
538 | ||
539 | \begin{verbatim} | |
540 | data Oper : (* -> *) -> * -> * where | |
541 | Return : a -> Oper f a | |
542 | Bind : f a -> (a -> Oper f b) -> Oper f b | |
543 | ||
544 | instance Monad (Oper f) where | |
545 | return = Return | |
546 | ||
547 | bind g (Return x) = g x | |
548 | bind g (Bind x f) = Bind x (f >=> g) | |
549 | \end{verbatim} | |
550 | ||
551 | We can use the operational monad to combine various instructions | |
552 | together: for example, we can construct a stack-like language | |
553 | with the following instructions: | |
554 | ||
555 | \begin{verbatim} | |
556 | data StackInstr a where | |
557 | Pop : StackInstr Int | |
558 | Push : Int -> StackInstr () | |
559 | ||
560 | evaluate : Oper StackInstr a -> List Int -> a | |
561 | evaluate (Return x) _ = x | |
562 | evaluate (Bind Pop f) (s:ss) = evaluate (f s) ss | |
563 | evaluate (Bind (Push s) f) ss = evaluate (f ()) (s:ss) | |
564 | ||
565 | push : Oper StackInstr () | |
566 | push = return . Push | |
567 | ||
568 | pop : Oper StackInstr Int | |
569 | pop = return Pop | |
570 | ||
571 | add : Oper StackInstr () | |
572 | add = bind pop (\ x -> | |
573 | bind pop (\ y -> | |
574 | push (x + y))) | |
575 | ||
576 | sampleProgram : Int | |
577 | sampleProgram = evalute program [] | |
578 | where program = | |
579 | \end{verbatim} | |
580 | ||
581 | \end{document} |
1 | all: presentation.pdf | |
2 | ||
3 | presentation.pdf: presentation.tex | |
4 | pdflatex presentation.tex | |
5 | ||
6 | clean: | |
7 | rm -rf presentation.aux presentation.log presentation.pdf presentation.nav \ | |
8 | presentation.out presentation.snm presentation.toc presentation.vrb |
1 | \documentclass{beamer} | |
2 | \usepackage{cmbright} | |
3 | % \usepackage[usenames,dvipsnames]{color} | |
4 | \usepackage{listings} | |
5 | \usepackage{xcolor} | |
6 | \newcommand{\pos}[1]{\textcolor{red}{#1}} | |
7 | \newcommand{\postt}[1]{\textcolor{red}{\texttt{#1}}} | |
8 | \newcommand{\dual}[1]{\textcolor{blue}{#1}} | |
9 | \newcommand{\dualtt}[1]{\textcolor{blue}{\texttt{#1}}} | |
10 | ||
11 | \lstset{ keywordstyle={\bfseries} | |
12 | , keywordstyle=[2]\color{red}\bfseries | |
13 | , keywordstyle=[3]\color{blue}\bfseries | |
14 | , basicstyle=\scriptsize\ttfamily, | |
15 | , morekeywords={where,let,in,instance,type}, | |
16 | , morekeywords=[2]{data,case,of} | |
17 | , morekeywords=[3]{codata,merge} | |
18 | } | |
19 | ||
20 | \newenvironment{both} | |
21 | { \begin{tabular}{ p{2in} p{2in} } } | |
22 | { \\ \end{tabular} } | |
23 | \renewcommand{\ttdefault}{pcr} | |
24 | ||
25 | \title{Generalized Coalgebraic Codata Types} | |
26 | \subtitle{Excessive Amounts of Duality} | |
27 | \author{G.~Ritter \and K.~Foner} | |
28 | \date{\today} | |
29 | \subject{Computer Science} | |
30 | ||
31 | \begin{document} | |
32 | ||
33 | \frame{\titlepage} | |
34 | ||
35 | \begin{frame}[fragile] | |
36 | \frametitle{Data and Codata: An Introduction} | |
37 | \begin{both} | |
38 | \begin{lstlisting} | |
39 | ------------------- | |
40 | -- Defining data -- | |
41 | ||
42 | data Either a b | |
43 | = Left a | |
44 | | Right b | |
45 | ||
46 | ----------------------- | |
47 | -- Constructing data -- | |
48 | ||
49 | Left : a -> Either a b | |
50 | Right : b -> Either a b | |
51 | ||
52 | ---------------------- | |
53 | -- Destructing data -- | |
54 | ||
55 | f : Either Int Bool -> Bool | |
56 | f x = case x of | |
57 | Left i -> i == 0 | |
58 | Right b -> b | |
59 | \end{lstlisting} | |
60 | & | |
61 | \begin{lstlisting} | |
62 | --------------------- | |
63 | -- Defining codata -- | |
64 | ||
65 | codata Both a b | |
66 | = First a | |
67 | & Second b | |
68 | ||
69 | ------------------------ | |
70 | -- Destructing codata -- | |
71 | ||
72 | First : Both a b -> a | |
73 | Second : Both a b -> b | |
74 | ||
75 | ------------------------- | |
76 | -- Constructing codata -- | |
77 | ||
78 | g : Int -> Both Int Bool | |
79 | g x = merge | |
80 | First p <- x | |
81 | Second p <- x == 0 | |
82 | \end{lstlisting} | |
83 | \\ | |
84 | \end{both} | |
85 | \end{frame} | |
86 | ||
87 | \begin{frame}[fragile] | |
88 | \frametitle{Copatterns} | |
89 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
90 | codata Stream a = Head a & Tail (Stream a) | |
91 | ||
92 | zipWith : (a -> b -> c) -> Stream a -> | |
93 | Stream b -> Stream c | |
94 | Head (zipWith f s1 s2) = | |
95 | f (Head s1) (Head s2) | |
96 | Tail (zipWith f s1 s2) = | |
97 | zipWith f (Tail s1) (Tail s2) | |
98 | ||
99 | fibs : Stream Int | |
100 | Head fibs = 0 | |
101 | Head (Tail fibs) = 1 | |
102 | Tail (fibsTail@(Tail fibs)) = | |
103 | zipWith (+) fibs fibsTail | |
104 | \end{lstlisting} | |
105 | \end{frame} | |
106 | ||
107 | \begin{frame}[fragile] | |
108 | \frametitle{Copatterns} | |
109 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
110 | codata Stream a = Head a & Tail (Stream a) | |
111 | ||
112 | zipWith : (a -> b -> c) -> Stream a -> | |
113 | Stream b -> Stream c | |
114 | Head (zipWith f s1 s2) = | |
115 | f (Head s1) (Head s2) | |
116 | Tail (zipWith f s1 s2) = | |
117 | zipWith f (Tail s1) (Tail s2) | |
118 | ||
119 | merge | |
120 | Head _ = 0 | |
121 | Head (Tail _) = 1 | |
122 | Tail (fibsTail@(Tail fibs)) = | |
123 | zipWith (+) fibs fibsTail | |
124 | \end{lstlisting} | |
125 | \end{frame} | |
126 | ||
127 | \begin{frame}[fragile] | |
128 | \frametitle{Generalizing Types} | |
129 | \begin{both} | |
130 | \begin{lstlisting} | |
131 | data T: * -> * where | |
132 | U : Int -> T Int | |
133 | X : (T a,T a) -> T (a,a) | |
134 | ||
135 | -- | |
136 | ||
137 | U : Int -> T Int | |
138 | X : (T a,T a) -> T (a,a) | |
139 | ||
140 | -- | |
141 | ||
142 | sum : T a -> Int | |
143 | sum x = case x of | |
144 | U i -> i | |
145 | X (a, b) -> sum a + sum b | |
146 | \end{lstlisting} | |
147 | & | |
148 | \begin{lstlisting} | |
149 | codata T': * -> * where | |
150 | U' : T' Int -> Int | |
151 | X' : T' (a,a) -> (T' a,T' a) | |
152 | ||
153 | -- | |
154 | ||
155 | U' : T' Int -> Int | |
156 | X' : T' (a,a) -> (T' a,T' a) | |
157 | ||
158 | -- | |
159 | ||
160 | split : Int -> T' a | |
161 | split i = merge | |
162 | U' _ <- i | |
163 | X' _ <- ( split 1 | |
164 | , split (i-1) | |
165 | ) | |
166 | \end{lstlisting} | |
167 | \end{both} | |
168 | \end{frame} | |
169 | ||
170 | \begin{frame}[fragile] | |
171 | \frametitle{GCCTs} | |
172 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
173 | codata Wrapper: * -> * where | |
174 | G : Wrapper a -> a | |
175 | Z : Wrapper Int -> Bool | |
176 | ||
177 | mkBoolWrapper : Bool -> Wrapper Bool | |
178 | G (mkBoolWrapper b) = b | |
179 | ||
180 | mkIntWrapper : Int -> Wrapper Int | |
181 | G (mkIntWrapper i) = i | |
182 | Z (mkIntWrapper i) = i == 0 | |
183 | ||
184 | mkWrapper : a -> Wrapper a | |
185 | G (mkWrapper x) = x | |
186 | Z (mkWrapper x) = x == 0 | |
187 | \end{lstlisting} | |
188 | \end{frame} | |
189 | ||
190 | \begin{frame}[fragile] | |
191 | \frametitle{NFA} | |
192 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
193 | data S = A | B | C | |
194 | ||
195 | codata FSA: S -> * where | |
196 | aToB : FSA A -> FSA B | |
197 | bToC : FSA B -> FSA C | |
198 | aToC : FSA A -> FSA C | |
199 | cToA : FSA C -> FSA A | |
200 | ||
201 | aState : FSA A | |
202 | aState = merge | |
203 | cToA (aToC a) <- a | |
204 | cToA (bToC (aToB a)) <- a | |
205 | ||
206 | cToA . bToC . aToB == id | |
207 | cToA . aToB -- fails to type-check | |
208 | \end{lstlisting} | |
209 | \end{frame} | |
210 | ||
211 | \begin{frame}[fragile] | |
212 | \frametitle{NFA} | |
213 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
214 | codata FSA: S -> * where | |
215 | aToB : FSA A -> FSA B | |
216 | bToC : FSA B -> FSA C | |
217 | aToC : FSA A -> FSA C | |
218 | cToA : FSA C -> FSA A | |
219 | matchedString : FSA A -> String | |
220 | ||
221 | aState : FSA A | |
222 | aState = | |
223 | let f str = merge | |
224 | cToA (aToC _) <- f (str ++ "ca") | |
225 | cToA (bToC (aToB _)) <- f (str ++ "bca") | |
226 | matchedString _ <- str | |
227 | in f "a" | |
228 | \end{lstlisting} | |
229 | \end{frame} | |
230 | ||
231 | \begin{frame}[fragile] | |
232 | \frametitle{NFA} | |
233 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
234 | codata FSA: S -> * where | |
235 | aToB : FSA A -> FSA B | |
236 | bToC : FSA B -> FSA C | |
237 | aToC : FSA A -> FSA C | |
238 | cToA : FSA C -> FSA A | |
239 | matchedString : FSA _ -> String | |
240 | ||
241 | aState : FSA A | |
242 | aState = | |
243 | let f str = merge | |
244 | cToA (aToC _) <- f (str ++ "ca") | |
245 | cToA (bToC (aToB _)) <- f (str ++ "bca") | |
246 | matchedString _ <- str | |
247 | matchedString (aToB _) <- str ++ "b" | |
248 | matchedString (aToC _) <- str ++ "c" | |
249 | matchedString (bToC (aToB _)) <- str ++ "bc" | |
250 | in f "a" | |
251 | \end{lstlisting} | |
252 | \end{frame} | |
253 | ||
254 | \begin{frame}[fragile] | |
255 | \frametitle{Operational} | |
256 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
257 | data Oper : (* -> *) -> * -> * where | |
258 | Return : a -> Oper t a | |
259 | Bind : t a -> (a -> Oper t b) -> Oper t b | |
260 | ||
261 | instance Monad (Oper t) where | |
262 | return = Return | |
263 | Return x >>= g = g x | |
264 | Bind x f >>= g = Bind x (f >=> g) | |
265 | \end{lstlisting} | |
266 | \end{frame} | |
267 | ||
268 | \begin{frame}[fragile] | |
269 | \frametitle{Co-operational} | |
270 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
271 | codata Coop : (* -> *) -> * -> * where | |
272 | Extract : Coop t a -> a | |
273 | Extend : Coop t a -> (Coop t a -> b) -> t b | |
274 | ||
275 | instance Comonad (Coop t) where | |
276 | extract = Extract | |
277 | Extract (x <<= f) = f x | |
278 | Extend (x <<= f) g = | |
279 | Extend x (f =>= g) | |
280 | \end{lstlisting} | |
281 | \end{frame} | |
282 | ||
283 | \begin{frame}[fragile] | |
284 | \frametitle{Co-operational} | |
285 | \begin{lstlisting}[basicstyle=\normalsize\ttfamily] | |
286 | codata Op : * -> * where | |
287 | Pop : Op (a, b) -> a | |
288 | Drop : Op (a, b) -> Op b | |
289 | ||
290 | type Stack a = Coop Op a | |
291 | ||
292 | push : a -> Stack b -> Stack (a, b) | |
293 | push x s = s <<= go | |
294 | where go y = (x, extract y) | |
295 | ||
296 | dup : Stack (a, b) -> Stack (a, (a, b)) | |
297 | dup s = s <<= go | |
298 | where go y = (fst (extract y), extract y) | |
299 | \end{lstlisting} | |
300 | \end{frame} | |
301 | ||
302 | \end{document} |