Getting started with OCaml

Samuel Mimram

We recall here some basic constructions about OCaml. Some good and more detailed references are

1 The editor

In order to edit OCaml files, you can either use VS Code or Emacs. There is a specific page with the shortcuts to help you in both cases.

2 Functional OCaml

2.1 Values

Declaring values:

let x = 2 * 3

Local declarations:

let x =
  let y = 2 + 2 in
  y * y

Commands:

let () =
  print_endline "Hello, world!";
  print_endline "Bye."

2.2 Functions

Defining functions:

let f x = 2 * x

With multiple arguments:

let f b x y =
  if b then x else y

With a unit argument:

let f () =
  print_endline
    ("Time since the beginning of execution: "
     ^ string_of_float (Sys.time ()) ^ " seconds")

Recursive:

let rec fact n =
  if n = 0 then 1 else n * (fact (n-1))

Mutually recursive:

let rec even n =
  if n = 0 then true
  else odd (n-1)

and odd n =
  if n = 0 then false
  else even (n-1)

Unnamed functions:

let twice f =
  (fun f x -> f (f x)) f

2.3 Control

Conditional branching:

let () =
  print_endline (if Random.bool () then "true" else "false")

While loops:

let syracuse n =
  let r = ref n in
  while !r <> 1 do
    if !r mod 2 = 0 then r := !r / 2
    else r := 3 * !r + 1
  done

The usual boolean operations are

Equality =
Inequality <>
Conjunction &&
Disjunction ||
Negation not

You should never use == or != to compare things.

2.4 Pairs

A pair can be created with

(3, "hello")

A function taking a pair as argument

let fst (x, y) = x

2.5 Lists

The empty list

[]

A non-empty list

[1; 2; 3]

Appending an element:

let one_more l = 1::l

Length of a list:

let rec length =
  match l with
  | [] -> 0
  | x::l -> 1 + (length l)

See the documentation of the List module for (much) more.

2.6 Recursive types

Binary trees can be defined by

type 'a tree =
  | Node of 'a tree * 'a tree
  | Leaf of 'a

The maximal depth of a leaf is

let rec depth t =
  match t with
  | Node (t, u) -> max (depth t) (depth u)
  | Leaf _ -> 0

3 Imperative features

3.1 Printing

let () =
  print_endline "hello!"

3.2 References

let () =
  let r = ref 0 in
  while !r < 10 do
    print_int !r;
    r := !r + 1;
    print_endline ""
  done

The counter:

let count =
  let r = ref 0 in
  fun () ->
    r := !r + 1;
    !r

3.3 Exceptions

An exception can be defined with:

exception My_exception

It can be raised by

let f () =
  raise My_exception

It can be catched with

let test () =
  try
    f ();
    print_endline "not raised"
  with
  | My_exception -> "raised"

You can add tests in your code with

let () =
  assert (fact 5 = 120)

A failed test will raise

Assert_failure (...)

4 Typing

Some types:

# let x = 5;;
val x : int = 5
# let s = "hello";;
val s : string = "hello"
# let double x = 2 * x;;
val double : int -> int = <fun>
# let f () =
  print_endline "hello";;
val f : unit -> unit = <fun>
# let f x =
  print_endline ("The argument is " ^ string_of_int x);;
val f : int -> unit = <fun>
# let app f x = f x;;
val app : ('a -> 'b) -> 'a -> 'b = <fun>
# let fst (x, y) = x;;
val fst : 'a * 'b -> 'a = <fun>
# let rec map f l =
  match l with
  | [] -> []
  | x::l -> (f x)::(map f l);;
val map : ('a -> 'b) -> 'a list -> 'b list = <fun>

5 Compiling

An OCaml file prog.ml can be compiled with

ocamlopt prog.ml -o prog

and the resulting program can be executed with

./prog