## 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