0% found this document useful (0 votes)
75 views179 pages

Ocaml Tutorial

The document provides an introduction to the OCaml programming language. It begins by describing OCaml as a general purpose, strongly typed programming language that is part of the ML family. It then demonstrates a simple "Hello World" program to print a string. The document goes on to explain key OCaml concepts like declarations, variables, references, expressions versus statements, the unit type, local variables, and functions. It also provides examples of compiling and running OCaml code interactively.

Uploaded by

Frank
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
75 views179 pages

Ocaml Tutorial

The document provides an introduction to the OCaml programming language. It begins by describing OCaml as a general purpose, strongly typed programming language that is part of the ML family. It then demonstrates a simple "Hello World" program to print a string. The document goes on to explain key OCaml concepts like declarations, variables, references, expressions versus statements, the unit type, local variables, and functions. It also provides examples of compiling and running OCaml code interactively.

Uploaded by

Frank
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 179

École Polytechnique

INF549

A Short Introduction to OCaml


Jean-Christophe Filliâtre

September 11, 2018

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 1 / 102


overview

lecture Jean-Christophe Filliâtre


labs Stéphane Lengrand
Monday 17 and Tuesday 18, 9h–12h

web site for this course

http://www.enseignement.polytechnique.fr/profs/
informatique/Jean-Christophe.Filliatre/INF549/

questions ⇒ Jean-Christophe.Filliatre@lri.fr

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 2 / 102


OCaml

OCaml is a general-purpose, strongly typed programming language

successor of Caml Light (itself successor of Caml),


part of the ML family (SML, F#, etc.)

designed and implemented at Inria Rocquencourt by Xavier Leroy and


others

Some applications: symbolic computation and languages (IBM, Intel,


Dassault Systèmes), static analysis (Microsoft, ENS), file synchronization
(Unison), peer-to-peer (MLDonkey), finance (LexiFi, Jane Street Capital),
teaching

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 3 / 102


first steps with OCaml

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 4 / 102


the first program

hello.ml

print_string "hello world!\n"

compiling
% ocamlopt -o hello hello.ml

executing
% ./hello
hello world!

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 5 / 102


the first program

hello.ml

print_string "hello world!\n"

compiling
% ocamlopt -o hello hello.ml

executing
% ./hello
hello world!

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 5 / 102


the first program

hello.ml

print_string "hello world!\n"

compiling
% ocamlopt -o hello hello.ml

executing
% ./hello
hello world!

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 5 / 102


declarations

program = sequence of declarations and expressions to evaluate

let x = 1 + 2;;
print_int x;;
let y = x * x;;
print_int y;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 6 / 102


declarations

program = sequence of declarations and expressions to evaluate

let x = 1 + 2;;
print_int x;;
let y = x * x;;
print_int y;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 6 / 102


variable

let x = e introduces a global variable

differences wrt usual notion of variable:


1 necessarily initialized
2 type not declared but inferred
3 cannot be assigned

Java OCaml
final int x = 42; let x = 42

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 7 / 102


references

a variable to be assigned is called a reference

it is introduced with ref

let x = ref 1;;


print_int !x;;
x := !x + 1;;
print_int !x;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 8 / 102


references

a variable to be assigned is called a reference

it is introduced with ref

let x = ref 1;;


print_int !x;;
x := !x + 1;;
print_int !x;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 8 / 102


expressions and statements

no distinction between expression/statement in the syntax : only


expressions
usual constructs:
conditional
if i = 1 then 2 else 3

for loop
for i = 1 to 10 do x := !x + i done

sequence
x := 1; 2 * !x

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 9 / 102


expressions and statements

no distinction between expression/statement in the syntax : only


expressions
usual constructs:
conditional
if i = 1 then 2 else 3

for loop
for i = 1 to 10 do x := !x + i done

sequence
x := 1; 2 * !x

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 9 / 102


expressions and statements

no distinction between expression/statement in the syntax : only


expressions
usual constructs:
conditional
if i = 1 then 2 else 3

for loop
for i = 1 to 10 do x := !x + i done

sequence
x := 1; 2 * !x

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 9 / 102


expressions and statements

no distinction between expression/statement in the syntax : only


expressions
usual constructs:
conditional
if i = 1 then 2 else 3

for loop
for i = 1 to 10 do x := !x + i done

sequence
x := 1; 2 * !x

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 9 / 102


unit type

expressions with no meaningful value (assignment, loop, ...) have type


unit
this type has a single value, written ()

it is the type given to the else branch when it is omitted


correct:
if !x > 0 then x := 0

incorrect:
2 + (if !x > 0 then 1)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 10 / 102


unit type

expressions with no meaningful value (assignment, loop, ...) have type


unit
this type has a single value, written ()

it is the type given to the else branch when it is omitted


correct:
if !x > 0 then x := 0

incorrect:
2 + (if !x > 0 then 1)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 10 / 102


unit type

expressions with no meaningful value (assignment, loop, ...) have type


unit
this type has a single value, written ()

it is the type given to the else branch when it is omitted


correct:
if !x > 0 then x := 0

incorrect:
2 + (if !x > 0 then 1)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 10 / 102


local variables

in C or Java, the scope of a local variable extends to the bloc:


{
int x = 1;
...
}

in OCaml, a local variable is introduced with let in:


let x = 10 in x * x

as for a global variable:


necessarily initialized
type inferred
immutable
but scope limited to the expression following in

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 11 / 102


local variables

in C or Java, the scope of a local variable extends to the bloc:


{
int x = 1;
...
}

in OCaml, a local variable is introduced with let in:


let x = 10 in x * x

as for a global variable:


necessarily initialized
type inferred
immutable
but scope limited to the expression following in

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 11 / 102


local variables

in C or Java, the scope of a local variable extends to the bloc:


{
int x = 1;
...
}

in OCaml, a local variable is introduced with let in:


let x = 10 in x * x

as for a global variable:


necessarily initialized
type inferred
immutable
but scope limited to the expression following in

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 11 / 102


let in = expression

let x = e1 in e2 is an expression
its type and value are those of e2,
in an environment where x has the type and value of e1

example
let x = 1 in (let y = 2 in x + y) * (let z = 3 in x * z)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 12 / 102


let in = expression

let x = e1 in e2 is an expression
its type and value are those of e2,
in an environment where x has the type and value of e1

example
let x = 1 in (let y = 2 in x + y) * (let z = 3 in x * z)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 12 / 102


let in = expression

let x = e1 in e2 is an expression
its type and value are those of e2,
in an environment where x has the type and value of e1

example
let x = 1 in (let y = 2 in x + y) * (let z = 3 in x * z)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 12 / 102


parallel

Java OCaml
{ int x = 1; let x = ref 1 in
x = x + 1; x := !x + 1;
int y = x * x; let y = !x * !x in
System.out.print(y); } print int y

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 13 / 102


recap

program = sequence of expressions and declarations


variables introduced with let and immutable
no distinction expression / statement

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 14 / 102


interactive loop
interactive version of the compiler
% ocaml
OCaml version 4.02.3

# let x = 1 in x + 2;;

- : int = 3

# let y = 1 + 2;;

val y : int = 3

# y * y;;

- : int = 9

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 15 / 102


functions

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 16 / 102


syntax

# let f x = x * x;;

val f : int -> int = <fun>

body = expression (no return)


type is inferred (types of argument x and result)

# f 4;;

- : int = 16

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 17 / 102


syntax

# let f x = x * x;;

val f : int -> int = <fun>

body = expression (no return)


type is inferred (types of argument x and result)

# f 4;;

- : int = 16

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 17 / 102


syntax

# let f x = x * x;;

val f : int -> int = <fun>

body = expression (no return)


type is inferred (types of argument x and result)

# f 4;;

- : int = 16

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 17 / 102


syntax

# let f x = x * x;;

val f : int -> int = <fun>

body = expression (no return)


type is inferred (types of argument x and result)

# f 4;;

- : int = 16

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 17 / 102


parallel

Java OCaml
static int f(int x) { let f x =
return x * x; x * x
}

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 18 / 102


procedure
a procedure = a function whose result type is unit

example
# let x = ref 1;;
# let set v = x := v;;

val set : int -> unit = <fun>

# set 3;;

- : unit = ()

# !x;;

- : int = 3
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 19 / 102
procedure
a procedure = a function whose result type is unit

example
# let x = ref 1;;
# let set v = x := v;;

val set : int -> unit = <fun>

# set 3;;

- : unit = ()

# !x;;

- : int = 3
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 19 / 102
procedure
a procedure = a function whose result type is unit

example
# let x = ref 1;;
# let set v = x := v;;

val set : int -> unit = <fun>

# set 3;;

- : unit = ()

# !x;;

- : int = 3
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 19 / 102
procedure
a procedure = a function whose result type is unit

example
# let x = ref 1;;
# let set v = x := v;;

val set : int -> unit = <fun>

# set 3;;

- : unit = ()

# !x;;

- : int = 3
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 19 / 102
function without arguments

takes an argument of type unit

example
# let reset () = x := 0;;

val reset : unit -> unit = <fun>

# reset ();;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 20 / 102


function without arguments

takes an argument of type unit

example
# let reset () = x := 0;;

val reset : unit -> unit = <fun>

# reset ();;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 20 / 102


function with several arguments

# let f x y z = if x > 0 then y + x else z - x;;

val f : int -> int -> int -> int = <fun>

# f 1 2 3;;

- : int = 3

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 21 / 102


function with several arguments

# let f x y z = if x > 0 then y + x else z - x;;

val f : int -> int -> int -> int = <fun>

# f 1 2 3;;

- : int = 3

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 21 / 102


local function

function local to an expression


# let sqr x = x * x in sqr 3 + sqr 4 = sqr 5;;

- : bool = true

function local to another function


# let pythagorean x y z =
let sqr n = n * n in
sqr x + sqr y = sqr z;;

val pythagorean : int -> int -> int -> bool = <fun>

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 22 / 102


local function

function local to an expression


# let sqr x = x * x in sqr 3 + sqr 4 = sqr 5;;

- : bool = true

function local to another function


# let pythagorean x y z =
let sqr n = n * n in
sqr x + sqr y = sqr z;;

val pythagorean : int -> int -> int -> bool = <fun>

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 22 / 102


function as first-class citizen
function = yet another expression, introduced with fun
# fun x -> x+1

- : int -> int = <fun>

# (fun x -> x+1) 3;;

- : int = 4

internally
let f x = x+1;;
is identical to
let f = fun x -> x+1;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 23 / 102


function as first-class citizen
function = yet another expression, introduced with fun
# fun x -> x+1

- : int -> int = <fun>

# (fun x -> x+1) 3;;

- : int = 4

internally
let f x = x+1;;
is identical to
let f = fun x -> x+1;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 23 / 102


partial application
fun x y -> x*x + y*y
is the same as
fun x -> fun y -> x*x + y*y
one can apply a function partially
example
# let f x y = x*x + y*y;;

val f : int -> int -> int = <fun>


# let g = f 3;;

val g : int -> int = <fun>

# g 4;;

- : int = 25
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 24 / 102
partial application
fun x y -> x*x + y*y
is the same as
fun x -> fun y -> x*x + y*y
one can apply a function partially
example
# let f x y = x*x + y*y;;

val f : int -> int -> int = <fun>


# let g = f 3;;

val g : int -> int = <fun>

# g 4;;

- : int = 25
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 24 / 102
partial application

a partial application is a way to return a function


but one can also return a function as the result of a computation
# let f x = let x2 = x * x in fun y -> x2 + y * y;;

val f : int -> int -> int = <fun>

a partial application of f computes x*x only once

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 25 / 102


partial application: example
# let count_from n =
let r = ref (n-1) in fun () -> incr r; !r;;

val count_from : int -> unit -> int = <fun>

# let c = count_from 0;;

val c : unit -> int = <fun>

# c ();;

- : int = 0

# c ();;

- : int = 1
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 26 / 102
higher-order functions
a function may take functions as arguments
# let integral f =
let n = 100 in
let s = ref 0.0 in
for i = 0 to n-1 do
let x = float i /. float n in s := !s +. f x
done;
!s /. float n

# integral sin;;

- : float = 0.455486508387318301

# integral (fun x -> x*.x);;

- : float = 0.32835
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 27 / 102
iteration

in Java, one iterates over a collection with a cursor

for (Elt x: s) {
... do something with x ...
}

in OCaml, we typically write


iter (fun x -> ... do something with x ...) s
where iter is a function provided with the data structure, with type
val iter: (elt -> unit) -> set -> unit

example
iter (fun x -> Printf.printf "%s\n" x) s

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 28 / 102


iteration

in Java, one iterates over a collection with a cursor

for (Elt x: s) {
... do something with x ...
}

in OCaml, we typically write


iter (fun x -> ... do something with x ...) s
where iter is a function provided with the data structure, with type
val iter: (elt -> unit) -> set -> unit

example
iter (fun x -> Printf.printf "%s\n" x) s

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 28 / 102


difference wrt to function pointers

“in C one can pass and return function pointers”

but OCaml functions are more than function pointers


let f x = let x2 = x * x in fun y -> x2 + y * y;;
the value of x2 is captured in a closure

note: there are closures in Java (≥ 8) too


s.forEach(x -> { System.out.println(x); });

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 29 / 102


difference wrt to function pointers

“in C one can pass and return function pointers”

but OCaml functions are more than function pointers


let f x = let x2 = x * x in fun y -> x2 + y * y;;
the value of x2 is captured in a closure

note: there are closures in Java (≥ 8) too


s.forEach(x -> { System.out.println(x); });

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 29 / 102


recursive functions

in OCaml, it is idiomatic to use recursive functions, for


a function call is cheap
tail calls are optimized

example:
let zero f =
let rec lookup i = if f i = 0 then i else lookup (i+1) in
lookup 0

recursive code ⇒ clearer, simpler to justify

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 30 / 102


recursive functions

in OCaml, it is idiomatic to use recursive functions, for


a function call is cheap
tail calls are optimized

example:
let zero f =
let rec lookup i = if f i = 0 then i else lookup (i+1) in
lookup 0

recursive code ⇒ clearer, simpler to justify

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 30 / 102


polymorphism
# let f x = x;;

val f : ’a -> ’a = <fun>


# f 3;;

- : int = 3
# f true;;

- : bool = true

# f print_int;;

- : int -> unit = <fun>

# f print_int 1;;

1- : unit = ()
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 31 / 102
polymorphism
# let f x = x;;

val f : ’a -> ’a = <fun>


# f 3;;

- : int = 3
# f true;;

- : bool = true

# f print_int;;

- : int -> unit = <fun>

# f print_int 1;;

1- : unit = ()
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 31 / 102
polymorphism

OCaml always infers the most general type

example:
# let compose f g = fun x -> f (g x);;

val compose : (’a -> ’b) -> (’c -> ’a) -> ’c -> ’b = <fun>

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 32 / 102


polymorphism

OCaml always infers the most general type

example:
# let compose f g = fun x -> f (g x);;

val compose : (’a -> ’b) -> (’c -> ’a) -> ’c -> ’b = <fun>

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 32 / 102


recap

functions = first-class values: local, anonymous, arguments of other


functions, etc.
partially applied
polymorphic
function call is cheap

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 33 / 102


memory allocation

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 34 / 102


GC

memory allocation handled by a garbage collector (GC)

benefits:
unused memory is reclaimed automatically
efficient allocation

⇒ forget about “dynamic allocation is expensive”


... but keep worrying about complexity!

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 35 / 102


GC

memory allocation handled by a garbage collector (GC)

benefits:
unused memory is reclaimed automatically
efficient allocation

⇒ forget about “dynamic allocation is expensive”


... but keep worrying about complexity!

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 35 / 102


arrays
# let a = Array.make 10 0;;

val a : int array = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0|]


necessarily initialized
# let a = [| 1; 2; 3; 4 |];;

# a.(1);;

- : int = 2

# a.(1) <- 5;;

- : unit = ()

# a;;

- : int array = [|1; 5; 3; 4|]


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 36 / 102
arrays
# let a = Array.make 10 0;;

val a : int array = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0|]


necessarily initialized
# let a = [| 1; 2; 3; 4 |];;

# a.(1);;

- : int = 2

# a.(1) <- 5;;

- : unit = ()

# a;;

- : int array = [|1; 5; 3; 4|]


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 36 / 102
parallel

Java OCaml
int[] a = new int[42]; let a = Array.make 42 0

a[17] a.(17)

a[7] = 3; a.(7) <- 3

a.length Array.length a

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 37 / 102


example: insertion sort

let insertion_sort a =
let swap i j =
let t = a.(i) in a.(i) <- a.(j); a.(j) <- t
in
for i = 1 to Array.length a - 1 do
(* insert element a[i] in a[0..i-1] *)
let j = ref (i - 1) in
while !j >= 0 && a.(!j) > a.(!j + 1) do
swap !j (!j + 1); decr j
done
done

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 38 / 102


insertion sort

let insertion_sort a =
let swap i j =
let t = a.(i) in a.(i) <- a.(j); a.(j) <- t
in
for i = 1 to Array.length a - 1 do
(* insert element a[i] in a[0..i-1] *)
let rec insert j =
if j >= 0 && a.(j) > a.(j+1) then
begin swap j (j+1); insert (j-1) end
in
insert (i-1)
done

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 39 / 102


records

like in most programming languages


a record type is first declared
type complex = { re : float; im : float }

allocation and initialization are simultaneous:


# let x = { re = 1.0; im = -1.0 };;

val x : complex = {re = 1.; im = -1.}

# x.im;;

- : float = -1.

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 40 / 102


records

like in most programming languages


a record type is first declared
type complex = { re : float; im : float }

allocation and initialization are simultaneous:


# let x = { re = 1.0; im = -1.0 };;

val x : complex = {re = 1.; im = -1.}

# x.im;;

- : float = -1.

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 40 / 102


records

like in most programming languages


a record type is first declared
type complex = { re : float; im : float }

allocation and initialization are simultaneous:


# let x = { re = 1.0; im = -1.0 };;

val x : complex = {re = 1.; im = -1.}

# x.im;;

- : float = -1.

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 40 / 102


mutable fields

type person = { name : string; mutable age : int }

# let p = { name = "Martin"; age = 23 };;

val p : person = {name = "Martin"; age = 23}

# p.age <- p.age + 1;;

- : unit = ()

# p.age;;

- : int = 24

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 41 / 102


mutable fields

type person = { name : string; mutable age : int }

# let p = { name = "Martin"; age = 23 };;

val p : person = {name = "Martin"; age = 23}

# p.age <- p.age + 1;;

- : unit = ()

# p.age;;

- : int = 24

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 41 / 102


parallel

Java OCaml
class T { type t = {
final int v; boolean b; v: int;
T(int v, boolean b) { mutable b: bool;
this.v = v; this.b = b; }
}
}

T r = new T(42, true); let r = { v = 42; b = true }

r.b = false; r.b <- false

r.v r.v

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 42 / 102


references

a reference = a record of that predefined type


type ’a ref = { mutable contents : ’a }

ref, ! and := are syntactic sugar


only arrays and mutable fields can be mutated

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 43 / 102


references

a reference = a record of that predefined type


type ’a ref = { mutable contents : ’a }

ref, ! and := are syntactic sugar


only arrays and mutable fields can be mutated

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 43 / 102


references

a reference = a record of that predefined type


type ’a ref = { mutable contents : ’a }

ref, ! and := are syntactic sugar


only arrays and mutable fields can be mutated

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 43 / 102


tuples
usual notation
# (1,2,3);;

- : int * int * int = (1, 2, 3)

# let v = (1, true, "hello", ’a’);;

val v : int * bool * string * char =


(1, true, "hello", ’a’)

access to components
# let (a,b,c,d) = v;;

val a : int = 1
val b : bool = true
val c : string = "hello"
val d : char = ’a’
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 44 / 102
tuples
usual notation
# (1,2,3);;

- : int * int * int = (1, 2, 3)

# let v = (1, true, "hello", ’a’);;

val v : int * bool * string * char =


(1, true, "hello", ’a’)

access to components
# let (a,b,c,d) = v;;

val a : int = 1
val b : bool = true
val c : string = "hello"
val d : char = ’a’
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 44 / 102
tuples
useful to return several values
# let rec division n m =
if n < m then (0, n)
else let (q,r) = division (n - m) m in (q + 1, r);;

val division : int -> int -> int * int = <fun>

function taking a tuple as argument


# let f (x,y) = x + y;;

val f : int * int -> int = <fun>

# f (1,2);;

- : int = 3
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 45 / 102
tuples
useful to return several values
# let rec division n m =
if n < m then (0, n)
else let (q,r) = division (n - m) m in (q + 1, r);;

val division : int -> int -> int * int = <fun>

function taking a tuple as argument


# let f (x,y) = x + y;;

val f : int * int -> int = <fun>

# f (1,2);;

- : int = 3
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 45 / 102
lists

predefined type of lists, α list, immutable and homogeneous


built from the empty list [] and addition in front of a list ::

# let l = 1 :: 2 :: 3 :: [];;

val l : int list = [1; 2; 3]

shorter syntax
# let l = [1; 2; 3];;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 46 / 102


pattern matching
pattern matching = case analysis on a list
# let rec sum l =
match l with
| [] -> 0
| x :: r -> x + sum r;;

val sum : int list -> int = <fun>

# sum [1;2;3];;

- : int = 6

shorter notation for a function performing pattern matching on its


argument
let rec sum = function
| [] -> 0
| x :: r -> x + sum r;;
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 47 / 102
pattern matching
pattern matching = case analysis on a list
# let rec sum l =
match l with
| [] -> 0
| x :: r -> x + sum r;;

val sum : int list -> int = <fun>

# sum [1;2;3];;

- : int = 6

shorter notation for a function performing pattern matching on its


argument
let rec sum = function
| [] -> 0
| x :: r -> x + sum r;;
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 47 / 102
pattern matching
pattern matching = case analysis on a list
# let rec sum l =
match l with
| [] -> 0
| x :: r -> x + sum r;;

val sum : int list -> int = <fun>

# sum [1;2;3];;

- : int = 6

shorter notation for a function performing pattern matching on its


argument
let rec sum = function
| [] -> 0
| x :: r -> x + sum r;;
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 47 / 102
representation in memory

OCaml lists = identical to lists in C or Java

the list [1; 2; 3] is represented as

1 2 3 []

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 48 / 102


algebraic data types
lists = particular case of algebraic data type

algebraic data type = union of several constructors

type fmla = True | False | And of fmla * fmla

# True;;

- : fmla = True

# And (True, False);;

- : fmla = And (True, False)

lists predefined as
type ’a list = [] | :: of ’a * ’a list
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 49 / 102
algebraic data types
lists = particular case of algebraic data type

algebraic data type = union of several constructors

type fmla = True | False | And of fmla * fmla

# True;;

- : fmla = True

# And (True, False);;

- : fmla = And (True, False)

lists predefined as
type ’a list = [] | :: of ’a * ’a list
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 49 / 102
algebraic data types
lists = particular case of algebraic data type

algebraic data type = union of several constructors

type fmla = True | False | And of fmla * fmla

# True;;

- : fmla = True

# And (True, False);;

- : fmla = And (True, False)

lists predefined as
type ’a list = [] | :: of ’a * ’a list
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 49 / 102
algebraic data types
lists = particular case of algebraic data type

algebraic data type = union of several constructors

type fmla = True | False | And of fmla * fmla

# True;;

- : fmla = True

# And (True, False);;

- : fmla = And (True, False)

lists predefined as
type ’a list = [] | :: of ’a * ’a list
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 49 / 102
pattern matching

pattern matching generalizes to algebraic data types


# let rec eval = function
| True -> true
| False -> false
| And (f1, f2) -> eval f1 && eval f2;;

val eval : fmla -> bool = <fun>

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 50 / 102


pattern matching

patterns can be nested:


let rec eval = function
| True -> true
| False -> false
| And (False, f2) -> false
| And (f1, False) -> false
| And (f1, f2) -> eval f1 && eval f2;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 51 / 102


pattern matching

patterns can be omitted or grouped


let rec eval = function
| True -> true
| False -> false
| And (False, _) | And (_, False) -> false
| And (f1, f2) -> eval f1 && eval f2;;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 52 / 102


parallel
Java OCaml
abstract class Fmla { } type fmla =
class True extends Fmla { } | True
class False extends Fmla { } | False
class And extends Fmla { | And of fmla * fmla
Fmla f1, f2; }

abstract class Fmla { let rec eval = function


abstract boolean eval(); } | True -> true
class True { boolean eval() {
return true; } } | False -> false
class False { boolean eval() {
return false; } } | And (f1, f2) ->
class And { boolean eval() { eval f1 && eval f2
return f1.eval()&&f2.eval();
} }

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 53 / 102


pattern matching

pattern matching is not limited to algebraic data types


let rec mult = function
| [] -> 1
| 0 :: _ -> 0
| x :: l -> x * mult l

one may write let pattern = expression when there is a single pattern
(as in let (a,b,c,d) = v for instance)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 54 / 102


pattern matching

pattern matching is not limited to algebraic data types


let rec mult = function
| [] -> 1
| 0 :: _ -> 0
| x :: l -> x * mult l

one may write let pattern = expression when there is a single pattern
(as in let (a,b,c,d) = v for instance)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 54 / 102


recap

allocation is cheap
memory is reclaimed automatically
allocated values are necessarily initialized
most values cannot be mutated
(only arrays and mutable record fields can be)
efficient representation of values
pattern matching = case analysis over values

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 55 / 102


execution model

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 56 / 102


values

a value is
either a primitive value (integer, floating point, Boolean, [], etc.)
or a pointer (to an array, a constructor such as And, etc.)
it fits on 64 bits

passing mode is by value

in particular, no value is ever copied

it is exactly as in Java

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 57 / 102


no null value

in OCaml, there is no such thing as null

in particular, any value is necessarily initialized

sometimes a pain, but it’s worth the effort:


an expression of type τ whose evaluation terminates
necessarily has a legal value of type τ
this is known as strong typing

no such thing as NullPointerException


(neither segmentation fault as in C/C++)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 58 / 102


comparison

equality written == is physical equality,


that is, equality of pointers or primitive values
# (1, 2) == (1, 2);;

- : bool = false
as in Java

equality written =, on the contrary, is structural equality,


that is, recursive equality descending in sub-terms
# (1, 2) = (1, 2);;

- : bool = true
it is equivalent to equals in Java (when suitably defined)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 59 / 102


exceptions

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 60 / 102


exceptions

usual notion
an exception may be raised
let division n m =
if m = 0 then raise Division_by_zero else ...

and later caught


try division x y with Division_by_zero -> (0,0)

one can introduce new exceptions


exception Error
exception Unix_error of string

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 61 / 102


exceptions

usual notion
an exception may be raised
let division n m =
if m = 0 then raise Division_by_zero else ...

and later caught


try division x y with Division_by_zero -> (0,0)

one can introduce new exceptions


exception Error
exception Unix_error of string

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 61 / 102


exceptions

usual notion
an exception may be raised
let division n m =
if m = 0 then raise Division_by_zero else ...

and later caught


try division x y with Division_by_zero -> (0,0)

one can introduce new exceptions


exception Error
exception Unix_error of string

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 61 / 102


idiom

in OCaml, exceptions are used in the library to signal exceptional behavior

example: Not found to signal a missing value

try
let v = Hashtbl.find table key in
...
with Not_found ->
...
(where Java typically returns null)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 62 / 102


modules and functors

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 63 / 102


software engineering

when programs get big we need to


split code into units (modularity)
hide data representation (encapsulation)
avoid duplicating code

in OCaml, this is provided by modules

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 64 / 102


files and modules
each file is a module
if arith.ml contains
let pi = 3.141592
let round x = floor (x +. 0.5)
we compile it with
% ocamlopt -c arith.ml
we use it within another module main.ml:
let x = float_of_string (read_line ());;
print_float (Arith.round (x /. Arith.pi));;
print_newline ();;

% ocamlopt -c main.ml

% ocamlopt arith.cmx main.cmx


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 65 / 102
files and modules
each file is a module
if arith.ml contains
let pi = 3.141592
let round x = floor (x +. 0.5)
we compile it with
% ocamlopt -c arith.ml
we use it within another module main.ml:
let x = float_of_string (read_line ());;
print_float (Arith.round (x /. Arith.pi));;
print_newline ();;

% ocamlopt -c main.ml

% ocamlopt arith.cmx main.cmx


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 65 / 102
files and modules
each file is a module
if arith.ml contains
let pi = 3.141592
let round x = floor (x +. 0.5)
we compile it with
% ocamlopt -c arith.ml
we use it within another module main.ml:
let x = float_of_string (read_line ());;
print_float (Arith.round (x /. Arith.pi));;
print_newline ();;

% ocamlopt -c main.ml

% ocamlopt arith.cmx main.cmx


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 65 / 102
files and modules
each file is a module
if arith.ml contains
let pi = 3.141592
let round x = floor (x +. 0.5)
we compile it with
% ocamlopt -c arith.ml
we use it within another module main.ml:
let x = float_of_string (read_line ());;
print_float (Arith.round (x /. Arith.pi));;
print_newline ();;

% ocamlopt -c main.ml

% ocamlopt arith.cmx main.cmx


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 65 / 102
files and modules
each file is a module
if arith.ml contains
let pi = 3.141592
let round x = floor (x +. 0.5)
we compile it with
% ocamlopt -c arith.ml
we use it within another module main.ml:
let x = float_of_string (read_line ());;
print_float (Arith.round (x /. Arith.pi));;
print_newline ();;

% ocamlopt -c main.ml

% ocamlopt arith.cmx main.cmx


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 65 / 102
encapsulation

we can limit what is exported with an interface


in a file arith.mli
val round : float -> float

% ocamlopt -c arith.mli
% ocamlopt -c arith.ml

% ocamlopt -c main.ml
File "main.ml", line 2, characters 33-41:
Unbound value Arith.pi

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 66 / 102


encapsulation

we can limit what is exported with an interface


in a file arith.mli
val round : float -> float

% ocamlopt -c arith.mli
% ocamlopt -c arith.ml

% ocamlopt -c main.ml
File "main.ml", line 2, characters 33-41:
Unbound value Arith.pi

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 66 / 102


encapsulation

we can limit what is exported with an interface


in a file arith.mli
val round : float -> float

% ocamlopt -c arith.mli
% ocamlopt -c arith.ml

% ocamlopt -c main.ml
File "main.ml", line 2, characters 33-41:
Unbound value Arith.pi

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 66 / 102


encapsulation

we can limit what is exported with an interface


in a file arith.mli
val round : float -> float

% ocamlopt -c arith.mli
% ocamlopt -c arith.ml

% ocamlopt -c main.ml
File "main.ml", line 2, characters 33-41:
Unbound value Arith.pi

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 66 / 102


encapsulation

an interface may also hide the definition of a type


in set.ml
type t = int list
let empty = []
let add x l = x :: l
let mem = List.mem
but in set.mli
type t
val empty : t
val add : int -> t -> t
val mem : int -> t -> bool
type t is an abstract type

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 67 / 102


encapsulation

an interface may also hide the definition of a type


in set.ml
type t = int list
let empty = []
let add x l = x :: l
let mem = List.mem
but in set.mli
type t
val empty : t
val add : int -> t -> t
val mem : int -> t -> bool
type t is an abstract type

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 67 / 102


encapsulation

an interface may also hide the definition of a type


in set.ml
type t = int list
let empty = []
let add x l = x :: l
let mem = List.mem
but in set.mli
type t
val empty : t
val add : int -> t -> t
val mem : int -> t -> bool
type t is an abstract type

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 67 / 102


encapsulation

an interface may also hide the definition of a type


in set.ml
type t = int list
let empty = []
let add x l = x :: l
let mem = List.mem
but in set.mli
type t
val empty : t
val add : int -> t -> t
val mem : int -> t -> bool
type t is an abstract type

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 67 / 102


separate compilation

the compilation of a file only depends on the interfaces of the other files
⇒ fewer recompilation when a code changes but its interface does not

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 68 / 102


separate compilation

the compilation of a file only depends on the interfaces of the other files
⇒ fewer recompilation when a code changes but its interface does not

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 68 / 102


module system

not limited to files


module M = struct
let c = 100
let f x = c * x
end

module A = struct
let a = 2
module B = struct
let b = 3
let f x = a * b * x
end
let f x = B.f (x + 1)
end

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 69 / 102


module system

not limited to files


module M = struct
let c = 100
let f x = c * x
end

module A = struct
let a = 2
module B = struct
let b = 3
let f x = a * b * x
end
let f x = B.f (x + 1)
end

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 69 / 102


module system

not limited to files


module M = struct
let c = 100
let f x = c * x
end

module A = struct
let a = 2
module B = struct
let b = 3
let f x = a * b * x
end
let f x = B.f (x + 1)
end

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 69 / 102


module system

similar for interfaces


module type S = sig
val f : int -> int
end
interface constraint
module M : S = struct
let a = 2
let f x = a * x
end

# M.a;;

Unbound value M.a

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 70 / 102


module system

similar for interfaces


module type S = sig
val f : int -> int
end
interface constraint
module M : S = struct
let a = 2
let f x = a * x
end

# M.a;;

Unbound value M.a

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 70 / 102


module system

similar for interfaces


module type S = sig
val f : int -> int
end
interface constraint
module M : S = struct
let a = 2
let f x = a * x
end

# M.a;;

Unbound value M.a

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 70 / 102


module system

similar for interfaces


module type S = sig
val f : int -> int
end
interface constraint
module M : S = struct
let a = 2
let f x = a * x
end

# M.a;;

Unbound value M.a

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 70 / 102


recap

code split into units called modules


encapsulation of types and values, abstract types
separate compilation
organizes the name space

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 71 / 102


functors

functor = module parameterized with other modules

example: hash table


one has to parameterize wrt hash function and equality function

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 72 / 102


functors

functor = module parameterized with other modules

example: hash table


one has to parameterize wrt hash function and equality function

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 72 / 102


the solution: a functor

module type HashedType = sig


type elt
val hash: elt -> int
val eq : elt -> elt -> bool
end

module HashTable(X: HashedType) = struct ... end

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 73 / 102


functor definition

module HashTable(X: HashedType) = struct


type t = X.elt list array
let create n = Array.make n []
let add t x =
let i = (X.hash x) mod (Array.length t) in
t.(i) <- x :: t.(i)
let mem t x =
let i = (X.hash x) mod (Array.length t) in
List.exists (X.eq x) t.(i)
end
inside, X is used as any regular module

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 74 / 102


functor type

module HashTable(X: HashedType) : sig


type t
val create : int -> t
val add : t -> X.elt -> unit
val mem : t -> X.elt -> bool
end

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 75 / 102


functor use
module Int = struct
type elt = int
let hash x = abs x
let eq x y = x=y
end

module Hint = HashTable(Int)

# let t = Hint.create 17;;

val t : Hint.t = <abstr>


# Hint.add t 13;;

- : unit = ()

# Hint.add t 173;;

- : unit = ()
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 76 / 102
functor use
module Int = struct
type elt = int
let hash x = abs x
let eq x y = x=y
end

module Hint = HashTable(Int)

# let t = Hint.create 17;;

val t : Hint.t = <abstr>


# Hint.add t 13;;

- : unit = ()

# Hint.add t 173;;

- : unit = ()
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 76 / 102
functor use
module Int = struct
type elt = int
let hash x = abs x
let eq x y = x=y
end

module Hint = HashTable(Int)

# let t = Hint.create 17;;

val t : Hint.t = <abstr>


# Hint.add t 13;;

- : unit = ()

# Hint.add t 173;;

- : unit = ()
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 76 / 102
parallel

Java OCaml
interface HashedType<T> { module type HashedType = sig
type elt
int hash(); val hash: elt -> int
boolean eq(T x); val eq: elt -> elt -> bool
} end

class HashTable module HashTable(E: HashedType) =


<E extends HashedType<E>> { struct
... ...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 77 / 102


applications of functors

1 data structures parameterized with other data structures


Hashtbl.Make : hash tables
Set.Make : finite sets implemented with balanced trees
Map.Make : finite maps implemented with balanced trees

2 algorithms parameterized with data structures

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 78 / 102


example: Dijkstra’s algorithm

module Dijkstra
(G: sig
type graph
type vertex
val succ: graph -> vertex -> (vertex * float) list
end) :
sig
val shortest_path:
G.graph -> G.vertex -> G.vertex -> G.vertex list * float
end

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 79 / 102


persistence

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 80 / 102


immutable data structures

in OCaml, most data structures are immutable


(exceptions are arrays and records with mutable fields)

said otherwise:
a value is not modified by an operation,
but a new value is returned

terminology: this is called applicative programming or functional


programming

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 81 / 102


example of immutable structure: lists

let l = [1; 2; 3]

let l’ = 0 :: l

l’ l
0 1 2 3 []

no copy, but sharing

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 82 / 102


counterpart

adding an element at the end of the list is not simple:

l
1 2 3 0 []

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 83 / 102


concatenating two lists
let rec append l1 l2 = match l1 with
| [] -> l2
| x :: l -> x :: append l l2

let l = [1; 2; 3]
let l’ = [4; 5]
let l’’ = append l l ’

l l’
1 2 3 [] 4 5 []
l’’
1 2 3

blocs of l are copied, blocs of l’ are shared


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 84 / 102
concatenating two lists
let rec append l1 l2 = match l1 with
| [] -> l2
| x :: l -> x :: append l l2

let l = [1; 2; 3]
let l’ = [4; 5]
let l’’ = append l l ’

l l’
1 2 3 [] 4 5 []
l’’
1 2 3

blocs of l are copied, blocs of l’ are shared


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 84 / 102
concatenating two lists
let rec append l1 l2 = match l1 with
| [] -> l2
| x :: l -> x :: append l l2

let l = [1; 2; 3]
let l’ = [4; 5]
let l’’ = append l l ’

l l’
1 2 3 [] 4 5 []
l’’
1 2 3

blocs of l are copied, blocs of l’ are shared


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 84 / 102
mutable linked lists

note: one can implement traditional linked lists,


for instance with

type ’a mlist = Empty | Element of ’a element


and ’a element = { value: ’a; mutable next: ’a mlist }

but then be careful with sharing (aliasing )

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 85 / 102


another example: trees

type tree = Empty | Node of int * tree * tree

val add : int -> tree -> tree

12
12
20
20
42

again, few copies and mostly sharing


Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 86 / 102
benefits of persistence

1 correctness of programs
code is simpler
mathematical reasoning is possible

2 easy to perform backtracking


search algorithms
symbolic manipulation and scopes
error recovery

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 87 / 102


benefits of persistence

1 correctness of programs
code is simpler
mathematical reasoning is possible

2 easy to perform backtracking


search algorithms
symbolic manipulation and scopes
error recovery

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 87 / 102


persistence and backtracking (1)

search for a path in a maze


type state
val is_exit : state -> bool
type move
val moves : state -> move list
val move : state -> move -> state

let rec search e =


is_exit e || iter e (moves e)
and iter e = function
| [] -> false
| d :: r -> search (move d e) || iter e r

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 88 / 102


persistence and backtracking (1)

search for a path in a maze


type state
val is_exit : state -> bool
type move
val moves : state -> move list
val move : state -> move -> state

let rec search e =


is_exit e || iter e (moves e)
and iter e = function
| [] -> false
| d :: r -> search (move d e) || iter e r

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 88 / 102


persistence and backtracking (1)

search for a path in a maze


type state
val is_exit : state -> bool
type move
val moves : state -> move list
val move : state -> move -> state

let rec search e =


is_exit e || iter e (moves e)
and iter e = function
| [] -> false
| d :: r -> search (move d e) || iter e r

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 88 / 102


without persistence

with a mutable, global state

let rec search () =


is_exit () || iter (moves ())
and iter = function
| [] -> false
| d :: r -> (move d; search ()) || (undo d; iter r)

i.e. one has to undo the side effect


(here with a function undo, inverse of move)

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 89 / 102


persistence and backtracking (2)

simple Java fragments, represented with


type stmt =
| Return of string
| Var of string * int
| If of string * string * stmt list * stmt list

example:
int x = 1;
int z = 2;
if (x == z) {
int y = 2;
if (y == z) return y; else return z;
} else
return x;

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 90 / 102


persistence and backtracking (2)

let us check that any variable which is used was previously declared
(within a list of statements)

val check_stmt : string list -> stmt -> bool


val check_prog : string list -> stmt list -> bool

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 91 / 102


persistence and backtracking (2)
let rec check_instr vars = function
| Return x ->
List.mem x vars
| If (x, y, p1, p2) ->
List.mem x vars && List.mem y vars &&
check_prog vars p1 && check_prog vars p2
| Var _ ->
true

and check_prog vars = function


| [] ->
true
| Var (x, _) :: p ->
check_prog (x :: vars) p
| i :: p ->
check_instr vars i && check_prog vars p
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 92 / 102
persistence and backtracking (2)
let rec check_instr vars = function
| Return x ->
List.mem x vars
| If (x, y, p1, p2) ->
List.mem x vars && List.mem y vars &&
check_prog vars p1 && check_prog vars p2
| Var _ ->
true

and check_prog vars = function


| [] ->
true
| Var (x, _) :: p ->
check_prog (x :: vars) p
| i :: p ->
check_instr vars i && check_prog vars p
Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 92 / 102
persistence and backtracking (3)

a program handles a database

non atomic updates, requiring lot of computation

with a mutable state


try
... performs update on the database ...
with e ->
... rollback database to a consistent state ...
... handle the error ...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 93 / 102


persistence and backtracking (3)

a program handles a database

non atomic updates, requiring lot of computation

with a mutable state


try
... performs update on the database ...
with e ->
... rollback database to a consistent state ...
... handle the error ...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 93 / 102


persistence and backtracking (3)

a program handles a database

non atomic updates, requiring lot of computation

with a mutable state


try
... performs update on the database ...
with e ->
... rollback database to a consistent state ...
... handle the error ...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 93 / 102


persistence and backtracking (3)

with a persistent data structure


let bd = ref (... initial database ...)
...
try
bd := (... compute the update of !bd ...)
with e ->
... handle the error ...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 94 / 102


interface and persistence

the persistent nature of a type is not obvious


the signature provides implicit information
mutable data structure
type t
val create : unit -> t
val add : int -> t -> unit
val remove : int -> t -> unit
...
persistent data structure
type t
val empty : t
val add : int -> t -> t
val remove : int -> t -> t
...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 95 / 102


interface and persistence

the persistent nature of a type is not obvious


the signature provides implicit information
mutable data structure
type t
val create : unit -> t
val add : int -> t -> unit
val remove : int -> t -> unit
...
persistent data structure
type t
val empty : t
val add : int -> t -> t
val remove : int -> t -> t
...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 95 / 102


interface and persistence

the persistent nature of a type is not obvious


the signature provides implicit information
mutable data structure
type t
val create : unit -> t
val add : int -> t -> unit
val remove : int -> t -> unit
...
persistent data structure
type t
val empty : t
val add : int -> t -> t
val remove : int -> t -> t
...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 95 / 102


interface and persistence

the persistent nature of a type is not obvious


the signature provides implicit information
mutable data structure
type t
val create : unit -> t
val add : int -> t -> unit
val remove : int -> t -> unit
...
persistent data structure
type t
val empty : t
val add : int -> t -> t
val remove : int -> t -> t
...

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 95 / 102


persistence and side effects

persistence does not mean absence of side effects

persistent = observationally immutable

only one way

immutable ⇒ persistent

the reciprocal is wrong

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 96 / 102


example: persistent queues

type ’a t
val create : unit -> ’a t
val push : ’a -> ’a t -> ’a t
exception Empty
val pop : ’a t -> ’a * ’a t

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 97 / 102


example: persistent queues

idea: a queue is a pair of lists,


one for insertion, and one for extraction

input
6 5 4 []

output
1 2 3 []

stands for the queue → 6, 5, 4, 3, 2, 1 →

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 98 / 102


example: persistent queues

type ’a t = ’a list * ’a list

let create () = [], []

let push x (e,s) = (x :: e, s)

exception Empty

let pop = function


| e, x :: s -> x, (e,s)
| e, [] -> match List.rev e with
| x :: s -> x, ([], s)
| [] -> raise Empty

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 99 / 102


example: persistent queues

when accessing several times the same queue whose second list is empty,
we reverse several times the same list

let’s add a reference to register the list reversal the first time it is
performed
type ’a t = (’a list * ’a list) ref

the side effect is done “under the hood”, in a way not observable from the
user, the contents of the queue staying the same

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 100 / 102


example: persistent queues

let create () = ref ([], [])

let push x q = let e,s = !q in ref (x :: e, s)

exception Empty

let pop q = match !q with


| e, x :: s -> x, ref (e,s)
| e, [] -> match List.rev e with
| x :: s as r -> q := [], r; x, ref ([], s)
| [] -> raise Empty

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 101 / 102


example: persistent queues

let create () = ref ([], [])

let push x q = let e,s = !q in ref (x :: e, s)

exception Empty

let pop q = match !q with


| e, x :: s -> x, ref (e,s)
| e, [] -> match List.rev e with
| x :: s as r -> q := [], r; x, ref ([], s)
| [] -> raise Empty

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 101 / 102


recap

persistent structure = no observable modification


in OCaml: List, Set, Map
can be very efficient (lot of sharing, hidden side effects, no copies)
idea independent of OCaml

Jean-Christophe Filliâtre A Short Introduction to OCaml INF549 102 / 102

You might also like