let rec fib (n: int) : int = if n <= 0 then 0 else if n = 1 then 1 else fib (n-2) + fib (n-1) let _ = assert (fib 0 = 0) let _ = assert (fib 1 = 1) let _ = assert (fib 2 = 1) let _ = assert (fib 5 = 5) let rec is_prime (n: int) : bool = let rec is_prime_helper (m: int) : bool = if m = n then true else if n mod m = 0 then false else is_prime_helper (m+1) in is_prime_helper 2 let rec is_prime_style (n: int) : bool = let rec is_prime_helper (m: int) : bool = (m = n) || ((n mod m <> 0) && (is_prime_helper (m + 1))) in is_prime_helper 2 let _ = assert (is_prime 2) let _ = assert (is_prime 3) let _ = assert (is_prime 7) let _ = assert (not (is_prime 9)) (* Tuples *) let p : int * int = (1, 2) let c = let (a, b) = p in a + b let (a, b) = p let fst (a, _) = a let snd (_, b) = b let fst3 (a, _, _) = a let snd3 (_, b) = b let trd3 (_, _, c) = c let addtuple (a, b) = a + b let id (x: int) = x let id_string (x: string) = x let id_int_int (x: int * int) = x let id (x: 'a) : 'a = x let (x: int -> int) = id (* Most general type: 'a -> 'a *) let f (a, b) = (b, a) (* Most general type: 'a * 'b -> 'b * 'a *) let f (a, b) = (a, b);; (* val f : 'a * 'b -> 'a * 'b = *) let f (a, b) = (a, a) let rec fib_efficient (n: int) : int = let rec fib_last_two (n: int) : int * int = if n <= 0 then (0, 0) else if n = 1 then (1, 0) else let (a, b) = fib_last_two (n - 1) in (a + b, a) in fst (fib_last_two n) let _ = assert (fib_efficient 0 = 0) let _ = assert (fib_efficient 1 = 1) let _ = assert (fib_efficient 2 = 1) let _ = assert (fib_efficient 5 = 5) let _ = assert (fib_efficient 42 > 0)