Skip to content

05-FP-Higher-Order Functions

Map

OCaml
let rec map f lst =
	match lst with 
	| [] -> []
	| h::t -> f h :: map f t;;

Function type: (ab)a lstb lst

This general function is a function of functions. It is on the higher-order.

map can even be partially applied. map twice is a function of type

int list int list

Map applied in different ways

OCaml
(*anonymous function*)
let rec map2 f = fun x -> 
	match  x with 
	| [] -> []
	| h::t -> f h :: map2 f t;;
ocaml
(*anonymous function with pattern matching*)
let rec map3 f = function 
	| [] -> []
	| h::t -> f h :: map3 f t;;
ocaml
(*using scopes*)
let rec map4 f = function 
	| [] -> []
	| h::t -> let h' = f h in h' :: map4 f t;;

Head Recursions and Tail Recursion

Recursion are of different types

  • head: the recursive call is the firstly performed operator.
  • tail: the recursive call is the lastly performed operator.
  • Some recursions can be neither head nor tail.

The output must be put on the interface.

  • return (recursion on input)with output

with is the last operation.

  • return recursion on (input with output)

recursion is the last operation.

Tail Map

The output for tail recursion has to be accumulated. Initially, the accumulated output is empty.

ppCaPR

The recursion stops if the input is empty.

ocaml
let rec map_t_aux f acc = function 
	|	[]->acc
	| h::t -> map_t_aux f (acc@ [f h])t;; 
let rec map_tail f l = map_t_aux f [] l;;

But this implementation is not efficient.

  • @ takes O(n) time, while :: only takes O(1) time.
  • Then, map is O(n), but map_tail is O(n2).
ocaml
let rec rev_map_aux f acc = function 
	| []->acc
	| h::t  -> rev_map_aux f(f h:: acc) t;; 

let rev_map f l = rev_map_aux f [] l;;

To reverse the order of a list, we only need to call rev_map_aux but let f be the identity function.

OCaml
let id a = a ;;
let map_tail f l = rev_map_aux id [] (rev_map f l);;
  • map_tail is O(n) now.
  • List.rev is also works.

Filter

  • Another famous higher-order function is filter.
    • filter takes a logical test and a list as input, and
    • returns the list of elements who pass the test.
ocaml
let rec filter p = function 
 | [] -> []
 | h::t ->(if p h then [h] else [])@ filter p t;

Fold

fold combines a list of items as one. For example, summation, concatenation, etc. Different from map and filter , programmers need to define an initial value for fold when the list is empty.

OCaml
let rec fold f ini  = function 
	| [] -> ini
	| h::t -> f h (fold f ini t);;

Fold Right and Fold Left

Fold Right

ocaml
let rec fold_right f lst acc =
	match lst with 
	| [] -> acc
	| h::t -> f h (fold_right f t acc);;

Now, fold_right is exactly same as the system library List.fold_right.

fold_right is for the function which is right associative.

Fold Left

In each iteration of fold_left

  • the accumulation acc carries the result of folding first n elements from previous iterations;
  • the combine function f is applied on acc and n + 1-th element;
  • the result of combine is passed to the next iteration as the new acc, together with the tail as the new list.
ocaml
let rec fold_left f acc = function 
	| [] -> acc
	| h :: t -> fold_left f (f acc h) t;;