summaryrefslogtreecommitdiffhomepage
path: root/ocaml.html.markdown
blob: ae862f081cd2247edbebe918bf8c09fa55c19095 (plain)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
---
language: "OCaml"
contributors:
    - ["Daniil Baturin", "http://baturin.org/"]
---

OCaml is a strictly evaluated functional language with some imperative
features.

Along with StandardML and its dialects it belongs to ML language family.
Just like StandardML, there are both a compiler and an interpreter
for OCaml. The interpreter binary is normally called "ocaml" and
the compiler is "ocamlc.opt". There is also a bytecode compiler, "ocamlc",
but there are few reasons to use it.

It is strongly and statically typed, but instead of using manually written
type annotations it infers types of expressions using Hindley-Milner algorithm.
It makes type annotations unnecessary in most cases, but can be a major
source of confusion for beginners.

When you are in the top level loop, OCaml will print the inferred type
after you enter an expression.
```
# let inc x = x	+ 1 ;;
val inc : int -> int = <fun>
# let a = 99 ;;
val a : int = 99
```

For a source file you can use "ocamlc -i /path/to/file.ml" command
to print all names and signatures.

```
$ cat sigtest.ml 
let inc x = x + 1
let add x y = x + y

let a = 1 

$ ocamlc -i ./sigtest.ml 
val inc : int -> int
val add : int -> int -> int
val a : int
```
Note that type signatures of functions of multiple arguments are
written in curried form.

```ocaml
(* Comments are enclosed in (* and *). It's fine to nest comments. *)

(* There are no single-line comments *)


(** Variables and functions *)

(* Statements can be separated by double
   semicolon symbol, ";;".
   In many cases it's redundant, but in this tutorial we use it after
   every expression for easy pasting into the interpreter shell. *)

(* Variable and function declarations use "let" keyword. *)
let x = 10 ;;

(* Since OCaml uses type inference, you normally don't need to
   specify argument types explicitly. However, you can do it
   if you want or need to. *)
let inc_int (x: int) = x + 1 ;;

(* You need to mark recursive function definitions as such with "rec" keyword. *)
let rec factorial n =
    if n = 0 then 1
    else factorial n * factorial (n-1)
;;

(* Function application usually doesn't need parantheses around arguments *)
let fact_5 = factorial 5 ;;

(* ...unless the argument is an expression *)
let fact_4 = factorial (5-1) ;;
let sqr2 = sqr (-2) ;;

(* You can use multiple statements separated by semicolon in function body,
   but the last expression becomes its return value. This is useful when
   writing in imperative style. The simplest form of it is inserting a 
   debug print. *)
let print_and_return x = 
    print_endline (string_of_int x);
    x
;;

(* Every function must have at least one argument.
   Since some funcions naturally don't take any arguments, there's 
   "unit" type for it that has the only one value written as "()" *)
let print_hello () = print_endline "hello world" ;;

(* Note that you must specify "()" as argument when calling it. *)
print_hello () ;;

(* Calling a function with insufficient number of arguments
   does not cause an error, it produces a new function. *)
let make_inc x y = x + y ;; (* make_inc is int -> int -> int *)
let inc_2 = make_inc 2 ;;   (* inc_2 is int -> int *)
inc_2 3 ;; (* Evaluates to 5 *)


(* Since OCaml is a functional language, it lacks "procedures".
   Every function must return something. So functions that
   do not really return anything and are called solely for their
   side effects, like print_endline, return value of "unit" type. *)


(* Definitions can be chained with "let ... in" construct.
   This is roughly the same to assigning values to multiple
   variables before using them in expressions in imperative
   languages. *)
let x = 10 in
let y = 20 in
x + y ;;

(* Alternatively you can use "let ... in and ..." construct.
   This is especially useful for mutually recursive functions,
   with ordinary "let .. in" the compiler will complain about
   unbound values.
   It's hard to come up with a meaningful but self-contained
   example of mutually recursive functions, but that syntax
   works for non-recursive definitions too. *)
let a = 3 and b = 4 in a * b ;;


(** Operators **)

(* There is little distintion between operators and functions.
   Every operator can be called as a function. *)

(+) 3 4  (* Same as 3 + 4 *)

(* There's a number of built-in operators. One of unusual features is
   that OCaml doesn't just refrain from any implicit conversions
   between integers and floats, it also uses different operators
   for floats. *)
12 + 3 ;; (* Integer addition *)
12.0 +. 3.0 ;; (* Floating point addition *)

12 / 3 ;; (* Integer division *)
12.0 /. 3.0 ;; (* Floating point division *)
5 mod 2 ;; (* Remainder *)

(* Unary minus is a notable exception, it's polymorphic.
   However, it also has "pure" integer and float forms. *)
- 3 ;; (* Polymorphic, integer *)
- 4.5 ;; (* Polymorphicm float *)
~- 3 (* Integer only *)
~- 3.4 (* Type error *)
~-. 3.4 (* Float only *)

(* You can define your own operators or redefine existing ones.
   Unlike SML or Haskell, only selected symbols can be used
   for operator names and first symbol defines associativity
   and precedence rules.  *)
let (+) a b = a - b ;; (* Surprise maintenance programmers *)

(* More useful: a reciprocal operator for floats.
   Unary operators must start with "~" *)
let (~/) x = 1.0 /. x ;;
~/4.0 (* = 0.25 *)


(** Built-in datastructures *)

(* Lists are enclosed in square brackets, items are separated by
   semicolons. *)
let my_list = [1; 2; 3] ;;

(* Tuples are (optionally) enclosed in parantheses, items are separated
   by commas *)
let first_tuple = 3, 4 ;;
let second_tuple = (4, 5) ;;

(* Corollary: if you try to separate list items by commas, you get a list
   with a tuple inside, probably not what you want. *)
let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *)

(* You can access individual list items with List.nth function *)
List.nth my_list 1 ;;

(* You can add an item to the beginning of a list with "::" constructor
   often referred to as "cons". *)
1 :: [2; 3] ;; (* Gives [1; 2; 3] *)

(* Arrays are enclosed in [| |] *)
let my_array = [| 1; 2; 3 |] ;;

(* You can access array items like this: *)
my_array.(0) ;;



(** Data types *)

(* You can define types with "type some_type =" construct. Like in this
   useless type alias: *)
type my_int = int ;;

(* More interesting types include so called type constructors.
   Constructors must start with a capital letter. *)
type ml = OCaml | StandardML ;;
let lang = OCaml ;;  (* Has type "ml" *)

(* Type constructors don't need to be empty. *)
type my_number = PlusInfinity | MinusInfinity | Real of float ;;
let r0 = Real -3.4 ;; (* Has type "my_number" *)

(* Can be used to implement polymorphic arithmetics. *)
type number = Int of int | Float of float ;;

(* Point on a plane, essentially a type-constrained tuple *)
type point2d = Point of float * float ;;
let my_point = Point (2.0, 3.0) ;;

(* Types can be parametrized, like in this type for "list of lists
   of anything". 'a can be substituted with any type. *)
type 'a list_of_lists = 'a list list ;;
type int_list_list = int list_of_lists ;;

(* Types also can be recursive. Like in this type analogous to
   built-in list of integers. *)
type my_int_list = EmptyList | IntList of int * my_int_list ;;
let l = Cons (1, EmptyList) ;;


(** Pattern matching *)

(* Pattern matching is somewhat similar to switch statement in imperative
   languages, but offers a lot more expressive power.

   Even though it may look complicated, it really boils down to matching 
   an argument against an exact value, a predicate, or a type constructor. The type system
   is what makes it so powerful. *)

(* Matching exact values. "_" means "anything" *)
let is_zero x =
    match x with
    | 0 -> true
    | _ -> false
;;

(* Alternatively, you can use "function" keyword *)
let is_one x = function
| 1 -> true
| _ -> false
;;

(* Matching predicates, aka "guarded pattern matching" *)
let abs x = 
    match x with
    | x when x < 0 -> -x
    | _ -> x
;;

abs 5 ;; (* 5 *)
abs (-5) (* 5 again *)

(* Matching type constructors *)

type animal = Dog of string | Cat of string ;;

let say x =
    match x with
    | Dog x -> x ^ " says woof"
    | Cat x -> x ^ " says meow"
;;

say (Cat "Fluffy") ;; (* "Fluffy says meow" *)

(* Traversing data structures *)

(* Recursive types can be traversed with pattern matching easily.
   The cons thing ("::") that is used with built-in lists is actually a
   type constructor, except it can be used in infix form, unlike 
   user-defined constructors. So you can use it like this: *)

let rec sum_list l =
    match l with
    | [] -> 0
    | head :: tail -> head + (sum_list tail)
;;

sum_list [1; 2; 3] ;;

(* Built-int syntax for cons obscures the structure a bit, so we'll make
   our own list for demonstration. *)

type int_list = Nil | Cons of int * int_list ;;
let rec sum_int_list l =
  match l with
      | Nil -> 0
      | Cons (head, tail) -> head + (sum_int_list tail)
;;

let t = Cons (1, Cons (2, Cons (3, Nil))) ;;
sum_int_list t ;;

```

## Further reading

* Visit the official website to get the compiler and read the docs: http://ocaml.org/
* Try interactive tutorials and a web-based interpreter by OCaml Pro: http://try.ocamlpro.com/
* Read "OCaml for the skeptical" course: http://www2.lib.uchicago.edu/keith/ocaml-class/home.html