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 are strongly advised to use Emacs. There are better looking editors for OCaml, but you will have to use Emacs for Agda anyway, so that it is better to get used to it right now. Have a look at the shortcuts.

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