(* implementing map and fold (reduce/accumulate) on 'a list_ type *) type 'a list_ = Nil | Cons of 'a * 'a list_ let il : int list_ = Cons (1, Cons (2, Cons (3, Nil))) (* [1; 2; 3] *) (* apply the function f to each element returning a new list * map f [a; b; c] = [f a; f b; f c] *) let rec map (f : 'a -> 'b) (x : 'a list_) : 'b list_ = match x with | Nil -> Nil | Cons (h, t) -> Cons (f h, map f t) let test = map string_of_int il let test = map (fun x -> x * x) il (* Copying a list using map *) let copy l = map (fun x -> x) l (* apply the function f to each element and accumulator, return new accumulator * fold_right f [a; b; c] r = f a (f b (f c r)) * also called reduce *) let rec fold_right (f : 'a -> 'b -> 'b) (lst : 'a list_) (r : 'b) : 'b = match lst with | Nil -> r | Cons (h, t) -> f h (fold_right f t r) let test = List.fold_right let test = fold_right let test = fold_right (fun x y -> string_of_int x ^ " " ^ y) il "" (* defining map in terms of fold_right *) let mapp f l = (fold_right (fun x y -> Cons ((f x), y)) l Nil) let test = mapp (fun x -> x * x) il (* apply the function f to accumulator and each element, return new accumulator * fold_left f r [a; b; c] = f (f (f r a) b) c *) let rec fold_left (f : 'a -> 'b -> 'a) (r : 'a) (lst : 'b list_) : 'a = match lst with | Nil -> r | Cons (h, t) -> fold_left f (f r h) t let test = List.fold_left let test = fold_left let test = fold_left (fun x y -> x ^ " " ^ string_of_int y) "" il let test = fold_right (fun x y -> x + y) il 0 let test = fold_left (fun x y -> x + y) 0 il (* map and reverse using fold_left *) let maprev f l = fold_left (fun x y -> Cons ((f y), x)) Nil l let test = maprev (fun x -> x * x) il (* filtering list according to predicate f *) let filter f l = (fold_right (fun x y -> if f x then Cons (x, y) else y) l Nil) let evens = filter (fun x -> (x / 2) * 2 = x) let test = evens il (* defining length in terms of folding *) let length l = fold_left (fun x _ -> 1 + x) 0 l let test = length il