CSCI 2041

ADVANCED PROGRAMMING PRINCIPLES

List Functions:

for_all/exists, map2/fold2, init

List functions

Some common list programming idioms:

Check if every (some) element of a list has a property:

for_all ((<>) 0) [2; 3; 5; 1]

exists ((>) "gophers") ["badgers"; "buckeyes"; "bulldogs"]

Combine two lists into one (or fold them together)

map2 max [1; 3; 3; 7] [3; 1; 4; 2]

fold_left2 (fun acc x y -> acc +. x *. y) [1.; 0.; 1.] [2.; 0.; -0.5]

Create a list from a function:

init 90 (fun n -> string_of_int (n+10))

for_all and exists

for_all takes a predicate and a list and returns true if all elements in the list satisfy the predicate:

for_all p [1; 2; 3] ≡ (p 1) && (p 2) && (p 3)

exists takes a predicate and a list and returns true if some element in the list satisfies the predicate

exists p [1; 2; 3] ≡ (p 1) || (p 2) || (p 3)

What is the type of for_all and exists?

for_all : ('a -> bool) -> 'a list -> bool

How are for_all and exists implemented in Ocaml?

let rec for_all p l = match l with
 | [] -> true
 | h::t -> (p h) && (for_all p t)
let rec exists p l = match l with
| [] -> false
| h::t -> (p h) || (exists p t)

Implement all_caps : char list -> bool via for_all:

let all_caps = for_all (fun c -> Char.uppercase c = c)

Implement has_digits : char list -> bool via exists:

let has_digits = exists (function '0'..'9' -> true | _ -> false)

map2 and fold_left2

map2 combines two lists into one by applying its function argument to elements of both lists in order, so

map2 (+) [1; 3; 2; 6] [2; 7; 14; 3] ≡ [1+2; 3+7; 2+14; 6+3]
map2 (||) [true; false; false] [false; true; false] ≡ [true||false; false||true ; false || false]

What about map2 (fun x y -> (x,y)) [1;2;3] ["a";"b";"c"]?

What is the type of map2?

map2: ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list

How is it implemented in OCaml?

let rec map2 f l1 l2 = match (l1,l2) with
 | ([],[]) -> []
 | (h1::t1, h2::t2) -> (f h1 h2)::(map2 f t1 t2)

implement concatlists : string list -> string list -> string list via map2:

let concatlists = map2 (^)

fold_left2 folds two lists together by combining the elements of the two lists with the accumulator, so

fold_left2 (fun acc s1 s2 -> acc^s1^s2) "init" ["a"; "b"; "c"] ["x"; "y"; "z"]
           ≡ (("init" ^ "a"^"x") ^ ("b"^"y")) ^ ("c"^"z")

What is the type of fold_left2?

('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a

How is fold_left2 implemented in Ocaml?

let rec fold_left2 f acc l1 l2 = match (l1,l2) with
| ([],[]) -> acc
| (h1::t1, h2::t2) -> fold_left2 f (f acc h1 h2) t1 t2

implement dot : float list -> float list -> float list via fold_left2:

let dot = fold_left2 (fun a u v -> a +. (u *. v)) 0.

init

init creates a list by applying its second argument to each integer between 0 and its first argument, so:

init 3 ((+) 17) ≡ [(17+0); (17+1); (17+2)]

What is the type of init?

int -> (int -> 'a) -> 'a list

What is its Ocaml implementation?

let init n f = (* this is the actual way *)
  let rec linit i acc = if i = n then acc else linit ((f i)::acc) (i+1)
  in List.rev (linit 0 [])

implement explode using init:

let explode s = init (String.length s) (fun i -> s.[i])

cs2041.org

// reveal.js plugins