There is a rich set of functions on lists, that you can find in the List module. We will implement these from scratch in this section. Most of these functions can be extended from lists to other “container types”.
map
has a function act on each element of the list, and produces a new list with the results.filter
takes as input a predicate (a function returning true/false) and returns a list containing only those values that return true.fold_left
accumulates the values in the list, given an initial value and a function describing how to accumulate each new term.fold_right
does the same, but starting from the other end.iter
calls a function with no return value ('a -> unit
) on each element of the list.for_all
takes a predicate and a list and returns whether all elements of the list would return true.exists
takes a predicate and a list and returns whether at least one element of the list would return true.find
takes a predicate and a list and searches for the first element in the list satisfying the prediate.partition
takes a predicate and a list and returns two lists, one holding the values that the predicate returns as true and one holding those the predicate returns as false.We have already seen map
, fold_left
, fold_right
. We will now implement filter
in a couple of different ways, both directly and using fold_right
.
(* filter: ('a -> bool) -> 'a list -> 'a list *)
let rec filter p xs = match xs with
| [] -> []
| x :: xs' -> if p x
then x :: filter p xs'
else filter p xs'
let filter p xs = fold_right (fun x acc -> if p x then x :: acc else acc) xs []
let filter p xs =
let add_if_true x acc = if p x then x :: acc else acc
in fold_right add_if_true xs []
Question: Could we have used fold_left
? Try it!
Before some practice problems, let us implement iter
both via direct recursion and using folds:
(* iter: ('a -> unit) -> 'a list -> unit *)
let rec iter f xs = match xs with
| [] -> ()
| x :: xs' -> (f x; iter f xs')
let iter f xs = fold_left (fun x () -> f x) () xs
(* To test. Should print in that order *)
iter print_endline ["hi"; "there"; "you"];;
Note that using fold_right
here would not be right: It would have performed the applications in the reverse list order, usually not the desired effect.
rev
that reverses a list, using fold_left
.for_all
using fold_left
or fold_right
(ideally do it both ways). It should have type ('a -> bool) -> 'a list -> bool
.exists
using fold_left
or fold_right
(ideally do it both ways). It should also have type ('a -> bool) -> 'a list -> bool
.partition
both with a direct recursion and using fold_right
. It should have type ('a -> bool) -> 'a list -> 'a list * 'a list
.