reorg monad links
[lambda.git] / week6.mdwn
1 [[!toc]]
2
3 Polymorphic Types and System F
4 ------------------------------
5
6 [Notes still to be added. Hope you paid attention during seminar.]
7
8 <!--
9
10 1.      Product or record types, e.g. pairs and triples
11 2.      Sum or variant types; tagged or "disjoint" unions
12 3.      Maybe/option types; representing "out-of-band" values
13 4.      Zero/bottom types
14 5.      Unit type
15 6.      Inductive types (numbers, lists)
16 7.      "Pattern-matching" or type unpacking<p>
17 8.      The simply-typed lambda calculus<p>
18 9.      Parametric polymorphism, System F, "type inference"<p>
19 10.     [Phil/ling application] inner/outer domain semantics for positive free logic
20         <http://philosophy.ucdavis.edu/antonelli/papers/pegasus-JPL.pdf>
21 11.     [Phil/ling application] King vs Schiffer in King 2007, pp 103ff. [which paper?](http://rci.rutgers.edu/~jeffreck/pub.php)
22 12. [Phil/ling application] King and Pryor on that clauses, predicates vs singular property-designators
23 13.     Possible excursion: [Frege's "On Concept and Object"](http://www.persiangig.com/pages/download/?dl=http://sahmir.persiangig.com/document/Frege%27s%20Articles/On%20Concept%20And%20object%20%28Jstore%29.pdf)<p>
24
25 -->
26
27
28 Types in OCaml
29 --------------
30
31 OCaml has type inference: the system can often infer what the type of
32 an expression must be, based on the type of other known expressions.
33
34 For instance, if we type
35
36     # let f x = x + 3;;
37
38 The system replies with
39
40     val f : int -> int = <fun>
41
42 Since `+` is only defined on integers, it has type
43
44      # (+);;
45      - : int -> int -> int = <fun>
46
47 The parentheses are there to turn off the trick that allows the two
48 arguments of `+` to surround it in infix (for linguists, SOV) argument
49 order. That is,
50
51     # 3 + 4 = (+) 3 4;;
52     - : bool = true
53
54 In general, tuples with one element are identical to their one
55 element:
56
57     # (3) = 3;;
58     - : bool = true
59
60 though OCaml, like many systems, refuses to try to prove whether two
61 functional objects may be identical:
62
63     # (f) = f;;
64     Exception: Invalid_argument "equal: functional value".
65
66 Oh well.
67
68 [Note: There is a limited way you can compare functions, using the
69 `==` operator instead of the `=` operator. Later when we discuss mutation,
70 we'll discuss the difference between these two equality operations.
71 Scheme has a similar pair, which they name `eq?` and `equal?`. In Python,
72 these are `is` and `==` respectively. It's unfortunate that OCaml uses `==` for the opposite operation that Python and many other languages use it for. In any case, OCaml will accept `(f) == f` even though it doesn't accept
73 `(f) = f`. However, don't expect it to figure out in general when two functions
74 are equivalent. (That question is not Turing computable.)
75
76         # (f) == (fun x -> x + 3);;
77         - : bool = false
78
79 Here OCaml says (correctly) that the two functions don't stand in the `==` relation, which basically means they're not represented in the same chunk of memory. However as the programmer can see, the functions are extensionally equivalent. The meaning of `==` is rather weird.]
80
81
82
83 Booleans in OCaml, and simple pattern matching
84 ----------------------------------------------
85
86 Where we would write `true 1 2` in our pure lambda calculus and expect
87 it to evaluate to `1`, in OCaml boolean types are not functions
88 (equivalently, they're functions that take zero arguments). Instead, selection is
89 accomplished as follows:
90
91     # if true then 1 else 2;;
92     - : int = 1
93
94 The types of the `then` clause and of the `else` clause must be the
95 same.
96
97 The `if` construction can be re-expressed by means of the following
98 pattern-matching expression:
99
100     match <bool expression> with true -> <expression1> | false -> <expression2>
101
102 That is,
103
104     # match true with true -> 1 | false -> 2;;
105     - : int = 1
106
107 Compare with
108
109     # match 3 with 1 -> 1 | 2 -> 4 | 3 -> 9;;
110     - : int = 9
111
112 Unit and thunks
113 ---------------
114
115 All functions in OCaml take exactly one argument.  Even this one:
116
117     # let f x y = x + y;;
118     # f 2 3;;
119     - : int = 5
120
121 Here's how to tell that `f` has been curry'd:
122
123     # f 2;;
124     - : int -> int = <fun>
125
126 After we've given our `f` one argument, it returns a function that is
127 still waiting for another argument.
128
129 There is a special type in OCaml called `unit`.  There is exactly one
130 object in this type, written `()`.  So
131
132     # ();;
133     - : unit = ()
134
135 Just as you can define functions that take constants for arguments
136
137     # let f 2 = 3;;
138     # f 2;;
139     - : int = 3;;
140
141 you can also define functions that take the unit as its argument, thus
142
143     # let f () = 3;;
144     val f : unit -> int = <fun>
145
146 Then the only argument you can possibly apply `f` to that is of the
147 correct type is the unit:
148
149     # f ();;
150     - : int = 3
151
152 Now why would that be useful?
153
154 Let's have some fun: think of `rec` as our `Y` combinator.  Then
155
156     # let rec f n = if (0 = n) then 1 else (n * (f (n - 1)));;
157     val f : int -> int = <fun>
158     # f 5;;
159     - : int = 120
160
161 We can't define a function that is exactly analogous to our &omega;.
162 We could try `let rec omega x = x x;;` what happens?
163
164 [Note: if you want to learn more OCaml, you might come back here someday and try:
165
166         # let id x = x;;
167         val id : 'a -> 'a = <fun>
168         # let unwrap (`Wrap a) = a;;
169         val unwrap : [< `Wrap of 'a ] -> 'a = <fun>
170         # let omega ((`Wrap x) as y) = x y;;
171         val omega : [< `Wrap of [> `Wrap of 'a ] -> 'b as 'a ] -> 'b = <fun>
172         # unwrap (omega (`Wrap id)) == id;;
173         - : bool = true
174         # unwrap (omega (`Wrap omega));;
175     <Infinite loop, need to control-c to interrupt>
176
177 But we won't try to explain this now.]
178
179
180 Even if we can't (easily) express omega in OCaml, we can do this:
181
182     # let rec blackhole x = blackhole x;;
183
184 By the way, what's the type of this function?
185
186 If you then apply this `blackhole` function to an argument,
187
188     # blackhole 3;;
189
190 the interpreter goes into an infinite loop, and you have to type control-c
191 to break the loop.
192
193 Oh, one more thing: lambda expressions look like this:
194
195     # (fun x -> x);;
196     - : 'a -> 'a = <fun>
197     # (fun x -> x) true;;
198     - : bool = true
199
200 (But `(fun x -> x x)` still won't work.)
201
202 You may also see this:
203
204         # (function x -> x);;
205         - : 'a -> 'a = <fun>
206
207 This works the same as `fun` in simple cases like this, and slightly differently in more complex cases. If you learn more OCaml, you'll read about the difference between them.
208
209 We can try our usual tricks:
210
211     # (fun x -> true) blackhole;;
212     - : bool = true
213
214 OCaml declined to try to fully reduce the argument before applying the
215 lambda function. Question: Why is that? Didn't we say that OCaml is a call-by-value/eager language?
216
217 Remember that `blackhole` is a function too, so we can
218 reverse the order of the arguments:
219
220     # blackhole (fun x -> true);;
221
222 Infinite loop.
223
224 Now consider the following variations in behavior:
225
226     # let test = blackhole blackhole;;
227     <Infinite loop, need to control-c to interrupt>
228
229     # let test () = blackhole blackhole;;
230     val test : unit -> 'a = <fun>
231
232     # test;;
233     - : unit -> 'a = <fun>
234
235     # test ();;
236     <Infinite loop, need to control-c to interrupt>
237
238 We can use functions that take arguments of type `unit` to control
239 execution.  In Scheme parlance, functions on the `unit` type are called
240 *thunks* (which I've always assumed was a blend of "think" and "chunk").
241
242 Question: why do thunks work? We know that `blackhole ()` doesn't terminate, so why do expressions like:
243
244         let f = fun () -> blackhole ()
245         in true
246
247 terminate?
248
249 Bottom type, divergence
250 -----------------------
251
252 Expressions that don't terminate all belong to the **bottom type**. This is a subtype of every other type. That is, anything of bottom type belongs to every other type as well. More advanced type systems have more examples of subtyping: for example, they might make `int` a subtype of `real`. But the core type system of OCaml doesn't have any general subtyping relations. (Neither does System F.) Just this one: that expressions of the bottom type also belong to every other type. It's as if every type definition in OCaml, even the built in ones, had an implicit extra clause:
253
254         type 'a option = None | Some of 'a;;
255         type 'a option = None | Some of 'a | bottom;;
256
257 Here are some exercises that may help better understand this. Figure out what is the type of each of the following:
258
259         fun x y -> y;;
260
261         fun x (y:int) -> y;;
262
263         fun x y : int -> y;;
264
265         let rec blackhole x = blackhole x in blackhole;;
266
267         let rec blackhole x = blackhole x in blackhole 1;;
268
269         let rec blackhole x = blackhole x in fun (y:int) -> blackhole y y y;;
270
271         let rec blackhole x = blackhole x in (blackhole 1) + 2;;
272
273         let rec blackhole x = blackhole x in (blackhole 1) || false;;
274
275         let rec blackhole x = blackhole x in 2 :: (blackhole 1);;
276
277 By the way, what's the type of this:
278
279         let rec blackhole (x:'a) : 'a = blackhole x in blackhole
280
281
282 Back to thunks: the reason you'd want to control evaluation with thunks is to
283 manipulate when "effects" happen. In a strongly normalizing system, like the
284 simply-typed lambda calculus or System F, there are no "effects." In Scheme and
285 OCaml, on the other hand, we can write programs that have effects. One sort of
286 effect is printing (think of the [[damn]] example at the start of term).
287 Another sort of effect is mutation, which we'll be looking at soon.
288 Continuations are yet another sort of effect. None of these are yet on the
289 table though. The only sort of effect we've got so far is *divergence* or
290 non-termination. So the only thing thunks are useful for yet is controlling
291 whether an expression that would diverge if we tried to fully evaluate it does
292 diverge. As we consider richer languages, thunks will become more useful.
293
294
295 Towards Monads
296 --------------
297
298 This has now been moved to [its own page](/towards_monads).
299