OCaml is a strictly evaluated functional language with some imperative features.
Along with Standard ML and its dialects it belongs to ML language family. F# is also heavily influenced by OCaml.
Just like Standard ML, OCaml features both an interpreter, that can be
used interactively, and a compiler.
The interpreter binary is normally called ocaml
and the compiler is ocamlopt
.
There is also a bytecode compiler, ocamlc
, but there are few reasons to use it.
It also includes a package manager, opam
, and a build system, dune
.
It is strongly and statically typed, but instead of using manually written type annotations, it infers types of expressions using the 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 the ocamlc -i /path/to/file.ml
command
to print all names and type 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.
A function that takes multiple arguments can be
represented as a composition of functions that take only one argument.
The f(x,y) = x + y
function from the example above applied to
arguments 2 and 3 is equivalent to the f0(y) = 2 + y
function applied to 3.
Hence the int -> int -> int
signature.
1(*** Comments ***)
2
3(* Comments are enclosed in (* and *). It's fine to nest comments. *)
4
5(* There are no single-line comments. *)
6
7
8(*** Variables and functions ***)
9
10(* Expressions can be separated by a double semicolon ";;".
11 In many cases it's redundant, but in this tutorial we use it after
12 every expression for easy pasting into the interpreter shell.
13 Unnecessary use of expression separators in source code files
14 is often considered to be a bad style. *)
15
16(* Variable and function declarations use the "let" keyword. *)
17(* Variables are immutable by default in OCaml *)
18let x = 10 ;;
19
20(* OCaml allows single quote characters in identifiers.
21 Single quote doesn't have a special meaning in this case, it's often used
22 in cases when in other languages one would use names like "foo_tmp". *)
23let foo = 1 ;;
24let foo' = foo * 2 ;;
25
26(* Since OCaml compiler infers types automatically, you normally don't need to
27 specify argument types explicitly. However, you can do it if
28 you want or need to. *)
29let inc_int (x: int) : int = x + 1 ;;
30
31(* One of the cases when explicit type annotations may be needed is
32 resolving ambiguity between two record types that have fields with
33 the same name. The alternative is to encapsulate those types in
34 modules, but both topics are a bit out of scope of this
35 tutorial. *)
36
37(* You need to mark recursive function definitions as such with "rec" keyword. *)
38let rec factorial n =
39 if n = 0 then 1
40 else n * factorial (n-1)
41;;
42
43(* Function application usually doesn't need parentheses around arguments *)
44let fact_5 = factorial 5 ;;
45
46(* ...unless the argument is an expression. *)
47let fact_4 = factorial (5-1) ;;
48let sqr2 = sqr (-2) ;;
49
50(* Every function must have at least one argument.
51 Since some functions naturally don't take any arguments, there's
52 "unit" type for it that has the only one value written as "()" *)
53let print_hello () = print_endline "hello world" ;;
54
55(* Note that you must specify "()" as the argument when calling it. *)
56print_hello () ;;
57
58(* Calling a function with an insufficient number of arguments
59 does not cause an error, it produces a new function. *)
60let make_inc x y = x + y ;; (* make_inc is int -> int -> int *)
61let inc_2 = make_inc 2 ;; (* inc_2 is int -> int *)
62inc_2 3 ;; (* Evaluates to 5 *)
63
64(* You can use multiple expressions in the function body.
65 The last expression becomes the return value. All other
66 expressions must be of the "unit" type.
67 This is useful when writing in imperative style, the simplest
68 form of which is inserting a debug print. *)
69let print_and_return x =
70 print_endline (string_of_int x);
71 x
72;;
73
74(* Since OCaml is a functional language, it lacks "procedures".
75 Every function must return something. So functions that do not
76 really return anything and are called solely for their side
77 effects, like print_endline, return a value of "unit" type. *)
78
79
80(* Definitions can be chained with the "let ... in" construct.
81 This is roughly the same as assigning values to multiple
82 variables before using them in expressions in imperative
83 languages. *)
84let x = 10 in
85let y = 20 in
86x + y ;;
87
88(* Alternatively you can use the "let ... and ... in" construct.
89 This is especially useful for mutually recursive functions,
90 with ordinary "let ... in" the compiler will complain about
91 unbound values. *)
92let rec
93 is_even = function
94 | 0 -> true
95 | n -> is_odd (n-1)
96and
97 is_odd = function
98 | 0 -> false
99 | n -> is_even (n-1)
100;;
101
102(* Anonymous functions use the following syntax: *)
103let my_lambda = fun x -> x * x ;;
104
105(*** Operators ***)
106
107(* There is little distinction between operators and functions.
108 Every operator can be called as a function. *)
109
110(+) 3 4 (* Same as 3 + 4 *)
111
112(* There's a number of built-in operators. One unusual feature is
113 that OCaml doesn't just refrain from any implicit conversions
114 between integers and floats, it also uses different operators
115 for floats. *)
11612 + 3 ;; (* Integer addition. *)
11712.0 +. 3.0 ;; (* Floating point addition. *)
118
11912 / 3 ;; (* Integer division. *)
12012.0 /. 3.0 ;; (* Floating point division. *)
1215 mod 2 ;; (* Remainder. *)
122
123(* Unary minus is a notable exception, it's polymorphic.
124 However, it also has "pure" integer and float forms. *)
125- 3 ;; (* Polymorphic, integer *)
126- 4.5 ;; (* Polymorphic, float *)
127~- 3 (* Integer only *)
128~- 3.4 (* Type error *)
129~-. 3.4 (* Float only *)
130
131(* You can define your own operators or redefine existing ones.
132 Unlike Standard ML or Haskell, only certain symbols can be
133 used for operator names and the operator's first symbol determines
134 its associativity and precedence rules. *)
135let (+) a b = a - b ;; (* Surprise maintenance programmers. *)
136
137(* More useful: a reciprocal operator for floats.
138 Unary operators must start with "~". *)
139let (~/) x = 1.0 /. x ;;
140~/4.0 (* = 0.25 *)
141
142
143(*** Built-in data structures ***)
144
145(* Lists are enclosed in square brackets, items are separated by
146 semicolons. *)
147let my_list = [1; 2; 3] ;; (* Has type "int list". *)
148
149(* Tuples are (optionally) enclosed in parentheses, items are separated
150 by commas. *)
151let first_tuple = 3, 4 ;; (* Has type "int * int". *)
152let second_tuple = (4, 5) ;;
153
154(* Corollary: if you try to separate list items by commas, you get a list
155 with a tuple inside, probably not what you want. *)
156let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *)
157
158(* You can access individual list items with the List.nth function. *)
159List.nth my_list 1 ;;
160
161(* There are higher-order functions for lists such as map and filter. *)
162List.map (fun x -> x * 2) [1; 2; 3] ;;
163List.filter (fun x -> x mod 2 = 0) [1; 2; 3; 4] ;;
164
165(* You can add an item to the beginning of a list with the "::" constructor
166 often referred to as "cons". *)
1671 :: [2; 3] ;; (* Gives [1; 2; 3] *)
168
169(* Remember that the cons :: constructor can only cons a single item to the front
170 of a list. To combine two lists use the append @ operator *)
171[1; 2] @ [3; 4] ;; (* Gives [1; 2; 3; 4] *)
172
173(* Arrays are enclosed in [| |] *)
174let my_array = [| 1; 2; 3 |] ;;
175
176(* You can access array items like this: *)
177my_array.(0) ;;
178
179
180(*** Strings and characters ***)
181
182(* Use double quotes for string literals. *)
183let my_str = "Hello world" ;;
184
185(* Use single quotes for character literals. *)
186let my_char = 'a' ;;
187
188(* Single and double quotes are not interchangeable. *)
189let bad_str = 'syntax error' ;; (* Syntax error. *)
190
191(* This will give you a single character string, not a character. *)
192let single_char_str = "w" ;;
193
194(* Strings can be concatenated with the "^" operator. *)
195let some_str = "hello" ^ "world" ;;
196
197(* Strings are not arrays of characters.
198 You can't mix characters and strings in expressions.
199 You can convert a character to a string with "String.make 1 my_char".
200 There are more convenient functions for this purpose in additional
201 libraries such as Core.Std that may not be installed and/or loaded
202 by default. *)
203let ocaml = (String.make 1 'O') ^ "Caml" ;;
204
205(* There is a printf function. *)
206Printf.printf "%d %s" 99 "bottles of beer" ;;
207
208(* There's also unformatted read and write functions. *)
209print_string "hello world\n" ;;
210print_endline "hello world" ;;
211let line = read_line () ;;
212
213
214(*** User-defined data types ***)
215
216(* You can define types with the "type some_type =" construct. Like in this
217 useless type alias: *)
218type my_int = int ;;
219
220(* More interesting types include so called type constructors.
221 Constructors must start with a capital letter. *)
222type ml = OCaml | StandardML ;;
223let lang = OCaml ;; (* Has type "ml". *)
224
225(* Type constructors don't need to be empty. *)
226type my_number = PlusInfinity | MinusInfinity | Real of float ;;
227let r0 = Real (-3.4) ;; (* Has type "my_number". *)
228
229(* Can be used to implement polymorphic arithmetics. *)
230type number = Int of int | Float of float ;;
231
232(* Point on a plane, essentially a type-constrained tuple *)
233type point2d = Point of float * float ;;
234let my_point = Point (2.0, 3.0) ;;
235
236(* Types can be parameterized, like in this type for "list of lists
237 of anything". 'a can be substituted with any type. *)
238type 'a list_of_lists = 'a list list ;;
239type int_list_list = int list_of_lists ;;
240
241(* These features allow for useful optional types *)
242type 'a option = Some of 'a | None ;;
243let x = Some x ;;
244let y = None ;;
245
246(* Types can also be recursive. Like in this type analogous to
247 a built-in list of integers. *)
248type my_int_list = EmptyList | IntList of int * my_int_list ;;
249let l = IntList (1, EmptyList) ;;
250
251(* or Trees *)
252type 'a tree =
253 | Empty
254 | Node of 'a tree * 'a * 'a tree
255
256let example_tree: int tree =
257 Node (
258 Node (Empty, 7, Empty),
259 5,
260 Node (Empty, 9, Empty)
261 )
262(*
263 5
264 / \
265 7 9
266*)
267
268(*** Records ***)
269
270(* A collection of values with named fields *)
271
272type animal =
273 {
274 name: string;
275 color: string;
276 legs: int;
277 }
278;;
279
280let cow =
281 { name = "cow";
282 color = "black and white";
283 legs = 4;
284 }
285;;
286val cow : animal
287
288cow.name ;;
289- : string = "cow"
290
291(*** Pattern matching ***)
292
293(* Pattern matching is somewhat similar to the switch statement in imperative
294 languages, but offers a lot more expressive power.
295
296 Even though it may look complicated, it really boils down to matching
297 an argument against an exact value, a predicate, or a type constructor.
298 The type system is what makes it so powerful. *)
299
300(** Matching exact values. **)
301
302let is_zero x =
303 match x with
304 | 0 -> true
305 | _ -> false (* The "_" means "anything else". *)
306;;
307
308(* Alternatively, you can use the "function" keyword. *)
309let is_one = function
310| 1 -> true
311| _ -> false
312;;
313
314(* Matching predicates, aka "guarded pattern matching". *)
315let abs x =
316 match x with
317 | x when x < 0 -> -x
318 | _ -> x
319;;
320
321abs 5 ;; (* 5 *)
322abs (-5) (* 5 again *)
323
324(** Matching type constructors **)
325
326type animal = Dog of string | Cat of string ;;
327
328let say x =
329 match x with
330 | Dog x -> x ^ " says woof"
331 | Cat x -> x ^ " says meow"
332;;
333
334say (Cat "Fluffy") ;; (* "Fluffy says meow". *)
335
336(* However, pattern matching must be exhaustive *)
337type color = Red | Blue | Green ;;
338let what_color x =
339 match x with
340 | Red -> "color is red"
341 | Blue -> "color is blue"
342 (* Won't compile! You have to add a _ case or a Green case
343 to ensure all possibilities are accounted for *)
344;;
345(* Also, the match statement checks each case in order.
346 So, if a _ case appears first, none of the
347 following cases will be reached! *)
348
349(** Traversing data structures with pattern matching **)
350
351(* Recursive types can be traversed with pattern matching easily.
352 Let's see how we can traverse a data structure of the built-in list type.
353 Even though the built-in cons ("::") looks like an infix operator,
354 it's actually a type constructor and can be matched like any other. *)
355let rec sum_list l =
356 match l with
357 | [] -> 0
358 | head :: tail -> head + (sum_list tail)
359;;
360
361sum_list [1; 2; 3] ;; (* Evaluates to 6 *)
362
363(* Built-in syntax for cons obscures the structure a bit, so we'll make
364 our own list for demonstration. *)
365
366type int_list = Nil | Cons of int * int_list ;;
367let rec sum_int_list l =
368 match l with
369 | Nil -> 0
370 | Cons (head, tail) -> head + (sum_int_list tail)
371;;
372
373let t = Cons (1, Cons (2, Cons (3, Nil))) ;;
374sum_int_list t ;;
375
376(* Heres a function to tell if a list is sorted *)
377let rec is_sorted l =
378 match l with
379 | x :: y :: tail -> x <= y && is_sorted (y :: tail)
380 | _ -> true
381;;
382
383is_sorted [1; 2; 3] ;; (* True *)
384(* OCaml's powerful type inference guesses that l is of type int list
385 since the <= operator is used on elements of l *)
386
387(* And another to reverse a list *)
388let rec rev (l: 'a list) : 'a list =
389 match l with
390 | [] -> []
391 | x::tl -> (rev tl) @ [x]
392;;
393
394rev [1; 2; 3] ;; (* Gives [3; 2; 1] *)
395(* This function works on lists of any element type *)
396
397(*** Higher Order Functions ***)
398
399(* Functions are first class in OCaml *)
400
401let rec transform (f: 'a -> 'b) (l: 'a list) : 'b list =
402 match l with
403 | [] -> []
404 | head :: tail -> (f head) :: transform f tail
405;;
406
407transform (fun x -> x + 1) [1; 2; 3] ;; (* Gives [2; 3; 4] *)
408
409(** Lets combine everything we learned! **)
410let rec filter (pred: 'a -> bool) (l: 'a list) : 'a list =
411 begin match l with
412 | [] -> []
413 | x :: xs ->
414 let rest = filter pred xs in
415 if pred x then x :: rest else rest
416 end
417;;
418
419filter (fun x -> x < 4) [3; 1; 4; 1; 5] ;; (* Gives [3; 1; 1]) *)
420
421(*** Mutability ***)
422
423(* Records and variables are immutable: you cannot change where a variable points to *)
424
425(* However, you can create mutable polymorphic fields *)
426type counter = { mutable num : int } ;;
427
428let c = { num = 0 } ;;
429c.num ;; (* Gives 0 *)
430c.num <- 1 ;; (* <- operator can set mutable record fields *)
431c.num ;; (* Gives 1 *)
432
433(* OCaml's standard library provides a ref type to make single field mutability easier *)
434type 'a ref = { mutable contents : 'a } ;;
435let counter = ref 0 ;;
436!counter ;; (* ! operator returns x.contents *)
437counter := !counter + 1 ;; (* := can be used to set contents *)
Further reading ¶
- Visit the official website to get the compiler and read the docs: http://ocaml.org/
- Quick tutorial on OCaml: https://ocaml.org/docs/up-and-running
- Complete online OCaml v5 playground: https://ocaml.org/play
- An up-to-date (2022) book (with free online version) «Real World OCaml»: https://www.cambridge.org/core/books/real-world-ocaml-functional-programming-for-the-masses/052E4BCCB09D56A0FE875DD81B1ED571
- Online interactive textbook «OCaml Programming: Correct + Efficient + Beautiful» from Cornell University: https://cs3110.github.io/textbook/cover.html
- Try interactive tutorials and a web-based interpreter by OCaml Pro: http://try.ocamlpro.com/