INF 231 - Functional Algorithmic and Programming

Lecture 1: Introduction, simple expressions and simple types

Example (basic function definition)

Very similar to the mathematical definition $$f : \mathbb{R} \to \mathbb {R},~ x\mapsto \exp(x) $$

In [102]:
let f (x:float) : float =
    exp(x);;
    
f 4.3 ;;
Out[102]:
val f : float -> float = <fun>
Out[102]:
- : float = 73.6997936995957872

Example (currying)

In [101]:
let area_rectangle (width:int)(length:int):int =
    width*length;;
    
area_rectangle 4 5;;    
    
let area_rectangle_of_width_2 = area_rectangle 2;;

area_rectangle_of_width_2 5;;
Out[101]:
val area_rectangle : int -> int -> int = <fun>
Out[101]:
- : int = 20
Out[101]:
val area_rectangle_of_width_2 : int -> int = <fun>
Out[101]:
- : int = 10

Example (factorial of an integer)

Simpler example: to compute $n!=n(n-1)\ldots 1$, on may note that $$n! = n\times (n-1)! $$ and that $$1!=1$$ This is again a strictly decreasing sequence, it must converge!

In [53]:
let rec fact (n:int):int =
    if (n=0 || n=1) then 1
    else n * fact (n-1);;

(*
let rec fact (n:int):int =
    if (n=0 || n=1) then (Printf.printf "Reached the end!";print_endline "";1)
    else (Printf.printf "Now computing %d * (fact %d)\n" n (n-1);n * fact (n-1));;
*)

fact 5;;
Out[53]:
val fact : int -> int = <fun>
Out[53]:
- : int = 120

Example (GCD of two integers $a$ and $b$)

An example with recursion: the function $\texttt{gcd}$ implements the observation that $$\texttt{gcd a b = gcd (a-b) b} $$ and so iteratively $$\texttt{gcd a b = gcd (a-2b) b} $$ $$\texttt{gcd a b = gcd (a-3b) b} $$ or equivalently in the end $$\texttt{gcd a b = gcd (a mod b) b} $$ so the numbers must $\textbf{strictly}$ decrease until reaching a point where $$\texttt{a mod b=0}$$

In [50]:
let rec gcd (a:int) (b:int) : int =
    let r = a mod b in 
        if r = 0 then b
        else gcd b r;;

(* 
let rec gcd (a:int) (b:int) : int =
    let r = a mod b in 
        if r = 0 then (Printf.printf "Found the gcd!";print_endline "";b)
        else (Printf.printf "Now computing gcd %d %d\n" b r;print_endline "";gcd b r);;
*)        

gcd 56 13;;
Out[50]:
val gcd : int -> int -> int = <fun>
Out[50]:
- : int = 1

Example (affine function)

Here the output is $\textbf{itself}$ a function.

In [57]:
let affine (a:int) (b:int):int -> int = 
    fun x -> a*x+b ;;

let f = affine 3 4;;

f 4;;
Out[57]:
val affine : int -> int -> int -> int = <fun>
Out[57]:
val f : int -> int = <fun>
Out[57]:
- : int = 16

Note that $\texttt{affine}$ has type "$\texttt{int -> int -> int -> int = <fun>}$". Where does it start, where does it end? In a way, everything in OCaml is functions:

In [65]:
let g = affine 3 ;;

g 4;;

g 4 5;;
Out[65]:
val g : int -> int -> int = <fun>
Out[65]:
- : int -> int = <fun>
Out[65]:
- : int = 19

Primitive types and basic expressions

Type $\texttt{int}$

In [67]:
1 + 3;;
1 + 2 + 3;;
-12;;

10/3;;
10 mod 3;;

lnot (-1);;
lnot 2;;
lnot 0b10;;

1 lsl 1;;
2 lsl 1;;
4 lsl 1;;
4 lsl 2;;
10 lsl 2;;

5 land 2;;
5 land 3;;
Out[67]:
- : int = 4
Out[67]:
- : int = 6
Out[67]:
- : int = -12
Out[67]:
- : int = 3
Out[67]:
- : int = 1
Out[67]:
- : int = 0
Out[67]:
- : int = -3
Out[67]:
- : int = -3
Out[67]:
- : int = 2
Out[67]:
- : int = 4
Out[67]:
- : int = 8
Out[67]:
- : int = 16
Out[67]:
- : int = 40
Out[67]:
- : int = 0
Out[67]:
- : int = 1

Type $\texttt{float}$

In [68]:
2. *. 3.14;;
10. /. 3.;;
float_of_int 10.;;
int_of_float 10.3;;
Out[68]:
- : float = 6.28
Out[68]:
- : float = 3.33333333333333348
File "[68]", line 3, characters 13-16:
Error: This expression has type float but an expression was expected of type
         int
   2: 10. /. 3.;;
   3: float_of_int 10.;;
   4: int_of_float 10.3;;

Type $\texttt{bool}$

In [99]:
true && false;;
true || false;;
not (true);;

true && (print_endline "coucou";false);;
false && (print_endline "coucou";true);;
Out[99]:
- : bool = false
Out[99]:
- : bool = true
Out[99]:
- : bool = false
coucou
Out[99]:
- : bool = false
Out[99]:
- : bool = false

difference between "$\texttt{=}$" and "$\texttt{==}$": beware of pointers! (same as in Python)

In [95]:
let a = [|0;1|];;
let b = a;;
let c = [|0;1|];;

(print_endline "b structurally equal to a?";b == a);;

(print_endline "c structurally equal to a?";c == a);;

(print_endline "c content equal to a?";c = a);;

a.(0) <- 2 ;;
b ;;
c ;;
Out[95]:
val a : int array = [|0; 1|]
Out[95]:
val b : int array = [|0; 1|]
Out[95]:
val c : int array = [|0; 1|]
b structurally equal to a?
Out[95]:
- : bool = true
c structurally equal to a?
Out[95]:
- : bool = false
c content equal to a?
Out[95]:
- : bool = true
Out[95]:
- : unit = ()
Out[95]:
- : int array = [|2; 1|]
Out[95]:
- : int array = [|0; 1|]

Type $\texttt{char}$

In [88]:
Char.code 'a';;
Char.code 'A';;
Char.code 'b';;
Char.code 'B';;
Char.uppercase_ascii 'a';;
Char.lowercase_ascii 'a';;
Out[88]:
- : int = 97
Out[88]:
- : int = 65
Out[88]:
- : int = 98
Out[88]:
- : int = 66
Out[88]:
- : char = 'A'
Out[88]:
- : char = 'a'

Type $\texttt{unit}$

In [104]:
();;
();1;;

let a = (print_endline "Hello!";3+4);;
Out[104]:
- : unit = ()
Out[104]:
- : int = 1
Hello!
Out[104]:
val a : int = 7

Even operators have a type!

In [105]:
(+);;
(<);;
Out[105]:
- : int -> int -> int = <fun>
Out[105]:
- : 'a -> 'a -> bool = <fun>

Be careful of associativity!

In [124]:
8 / (4 / 2);;
(8 / 4) / 2;;
8 / 4 / 2 ;;

(print_endline "Test 1";false) || (print_endline "Test 2";true) || (print_endline "Test 3";false) ;;
Out[124]:
- : int = 4
Out[124]:
- : int = 1
Out[124]:
- : int = 1
Test 1
Test 2
Out[124]:
- : bool = true

Constructs: if ... then ... else

In [128]:
if (1 > 2) then 'a' else 'b';;

if (true) then if false then 1 else 2 else 3;;

if (true) then print_endline "Ok!";;

if (true) then 2;;

if (false || true) then 'a' else 2;;
Out[128]:
- : char = 'b'
Out[128]:
- : int = 2
Ok!
Out[128]:
- : unit = ()
File "[128]", line 7, characters 15-16:
Error: This expression has type int but an expression was expected of type
         unit
       because it is in the result of a conditional with no else branch
   6: 
   7: if (true) then 2;;
   8: