CSCI 2041


intro Ocaml: functions and recursion

OCaml programs


A program is a sequence of expressions that are evaluated one after another.

Last time we saw primitive types, operators, let expressions, and conditionals…

We also saw function applications:

  • let res = fname arg applies function fname : t1 -> t2
  • to argument arg : t1
  • to compute result res : t2


A function is just another kind of value in OCaml:

  • They can be specified as: fun param-name -> expr

  • e.g. fun x -> x*x

  • let make_exciting = fun s -> s ^ "!"

Applying a function value to an argument binds the parameter name to the argument in the body, so:

  • (fun x -> x+1) 77+18
  • What about make_exciting "learn ocaml" ?

OCaml has syntactic “sugar”: for declaring functions, in particular:

let fname argname = expr is equivalent to let fname = fun argname -> expr, so:

  • let sqr r = r *. r ≡ let sqr = fun r -> r *. r

  • let triple x = 3*x in triple 0let triple = fun x -> 3*x in triple 0

Function types

What happens if we compile (make_exciting 7)?

If f has type τ1 -> τ2 and e has type matching τ1, then the application

(f e) has type matching τ2; otherwise applying f to e is a type error.

Function applications also introduce bindings: In

(fun param -> expr) arg

the scope of the binding from param to arg is the function body, expr.



Pure functional languages use recursion instead of iteration to express repeated code execution.

e.g. bn = b * bn-1, b0 = 1

let pow2 n =
    if n = 0 then 1
    else 2 * (pow2 (n-1))
in pow2 16

Oops! pow2 is not in scope

OCaml avoids this problem with the rec keyword:

 let rec pow2 n =
     if n = 0 then 1
     else 2 * (pow2 (n-1))
 in pow2 16

Recursive iteration

From earlier classes you have also seen recursive functions like fact : int -> int and fib : int -> int

Define a function starstr : int -> string so that starstr n is a string of n * characters:

let rec starstr n =
  if n <= 0 then "" else
  (starstr (n-1))^"*"

Multiple arguments

val pow2 : int -> int = <fun>
val starbar : int -> string = <fun>

What about multiple parameters, e.g. a*b?

let mul a b = a * b ;;
val mul : int -> int -> int = <fun>

Like let f x = expr is syntactic sugar for let f = fun x -> expr,

The form let f x y = expr is short for

let f = fun x -> (fun y -> expr)

Functions defined this way are called curried functions.

Partial application

OCaml has a language with rules for specifying types:

The operation -> is right-associative so the type

int -> int -> int

is the same type as

int -> (int -> int)

These multi-argument functions “eat their arguments” one at a time, so in

let mul x y = x*y
let f = mul 2

the value f is a result of a “partial application” of mul.

What does it do? What is its type?


What is the type of…

(fun x y z -> if x then y+z else z)
(fun x y z -> x ^ "," ^ y ^ "," ^ z) "hi"
mul 3.14

What is the result of:

let s = "lol"
let rec repeat_s t = if t = 0 then ""
  else s ^ (repeat_s (t-1))
let s = "zomg"
repeat_s 3

Here’s another way to define a multiple argument function:

let rec pow (b,n) = if n=0 then 1 else b * pow (b,n-1)

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

If expression e1 has type τ1 (so e1 : τ1) and e2 : τ2, then

  • The expression (e1, e2) : τ1 * τ2
  • (e1, e2, e3) : τ1 * τ2 * τ3.

These expressions are tuples, an example of structured data in OCaml

(The types of tuples are called product types)

// reveal.js plugins