6 OCAML has type inference: the system can often infer what the type of
7 an expression must be, based on the type of other known expressions.
9 For instance, if we type
13 The system replies with
15 val f : int -> int = <fun>
17 Since `+` is only defined on integers, it has type
20 - : int -> int -> int = <fun>
22 The parentheses are there to turn off the trick that allows the two
23 arguments of `+` to surround it in infix (for linguists, SOV) argument
29 In general, tuples with one element are identical to their one
35 though OCAML, like many systems, refuses to try to prove whether two
36 functional objects may be identical:
39 Exception: Invalid_argument "equal: functional value".
44 Booleans in OCAML, and simple pattern matching
45 ----------------------------------------------
47 Where we would write `true 1 2` and expect it to evaluate to `1`, in
48 OCAML boolean types are not functions (equivalently, are functions
49 that take zero arguments). Choices are made as follows:
51 # if true then 1 else 2;;
54 The types of the `then` clause and of the `else` clause must be the
57 The `if` construction can be re-expressed by means of the following
58 pattern-matching expression:
60 match <bool expression> with true -> <expression1> | false -> <expression2>
64 # match true with true -> 1 | false -> 2;;
69 # match 3 with 1 -> 1 | 2 -> 4 | 3 -> 9;;
75 All functions in OCAML take exactly one argument. Even this one:
81 Here's how to tell that `f` has been curry'd:
84 - : int -> int = <fun>
86 After we've given our `f` one argument, it returns a function that is
87 still waiting for another argument.
89 There is a special type in OCAML called `unit`. There is exactly one
90 object in this type, written `()`. So
95 Just as you can define functions that take constants for arguments
101 you can also define functions that take the unit as its argument, thus
104 val f : unit -> int = <fun>
106 Then the only argument you can possibly apply `f` to that is of the
107 correct type is the unit:
112 Let's have some fn: think of `rec` as our `Y` combinator. Then
114 # let rec f n = if (0 = n) then 1 else (n * (f (n - 1)));;
115 val f : int -> int = <fun>
119 We can't define a function that is exactly analogous to our ω.
120 We could try `let rec omega x = x x;;` what happens? However, we can
123 # let rec omega x = omega x;;
125 By the way, what's the type of this function?
126 If you then apply this omega to an argument,
130 the interpreter goes into an infinite loop, and you have to control-C
133 Oh, one more thing: lambda expressions look like this:
137 # (fun x -> x) true;;
140 (But `(fun x -> x x)` still won't work.)
142 So we can try our usual tricks:
144 # (fun x -> true) omega;;
147 OCAML declined to try to evaluate the argument before applying the
148 functor. But remember that `omega` is a function too, so we can
149 reverse the order of the arguments:
151 # omega (fun x -> true);;
155 Now consider the following differences:
157 # let test = omega omega;;
158 [Infinite loop, need to control c out]
160 # let test () = omega omega;;
161 val test : unit -> 'a = <fun>
164 - : unit -> 'a = <fun>
167 [Infinite loop, need to control c out]
169 We can use functions that take arguments of type unit to control
170 execution. In Scheme parlance, functions on the unit type are called
171 *thunks* (which I've always assumed was a blend of "think" and "chunk").