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 or Atom, which is more modern-looking but has less good support for OCaml. There are other editors for OCaml, but you will have to those anyway for Agda.

1.1 Emacs

You can start Emacs by typing emacs& and then go to the menu “File” > “Visit New File” in order to open a new file. Some useful shortcurts are following. C-x means the “control” and the “x” key at the same time, and M-x means “alt” and “x”. The standard shortcuts are

Shortcut Effect
C-x C-s save file
M-w copy
C-w cut
C-y paste
C-s find

and shortcuts specific to OCaml:

Shortcut Effect
C-e evaluate current function
C-c C-b evaluate the whole file
C-c C-t give the type of the term under the cursor

1.2 Atom

If you want a more modern-looking editor, with kind of standard shortcuts, you can use Atom. Apart from the standard shortcuts

Shortcut Effect
C-s save file
C-c copy
C-x cut
C-v paste
C-f find

the shortcuts specific to OCaml are

Shortcut Effect
C-y C-o launch and interactive session
C-y C-f evaluate the whole file

If you are working on your computer you should do the following to add support for OCaml (on TD rooms, this is taken care of for you). Go to the menu Edit > Preferences > Install, type “ocaml”, and install

1.3 Installing libraries

In order to install OCaml libraries on your own computer you should use opam. You only have to do the following if you are working on your own computer. Initialize it by typing, in a console,

opam init -y --disable-sandboxing

(this can take a few minutes, but has to be done only once). Then you are advised to install basic support for OCaml:

opam install -y tuareg merlin user-setup
opam user-setup install

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