(* Higher Order Functions *) let plus_two x = 2 + 2;; let compose f g = fun x -> f (g x);; plus_two;; compose plus_two plus_two;; compose plus_two;; (* Thrice *) let thrice f x = f (f (f x));; let thrice f = compose f (compose f f);; (* Reversing Arguments *) let rec map f list = match list with [] -> [] | (h::t) -> (f h) :: (map f t);; let flip f a b = f b a;; map ((-) 1) [5;6;7];; map (flip (-) 1) [5;6;7];; (* let (-) = flip (-);; 2 - 5;; *) (* Partial Application *) (+);; (+) 2 3;; let plus_two = (+) 2;; plus_two 7;; (* Lambda Lifting *) let add_two = (+) (print_string "test\n"; 2);; let add2 = (* lambda lifted *) fun x -> (+) (print_string "test\n"; 2) x;; (* Lambda Lifting *) thrice add_two 5;; thrice add2 5;; (* Partial Application and "Unknown Types" *) let f1 = compose plus_two;; let f2 = fun g -> compose plus_two g;; (* Partial Application and "Unknown Types" *) f1 plus_two;; (* f1 List.length;; *) (* Partial Application and "Unknown Types" *) f2 plus_two;; f2 List.length;; (* Curried vs Uncurried *) let curry f x y = f (x,y);; let uncurry f (x,y) = f x y;; (* curry and uncurry *) (+);; let plus = uncurry (+);; plus (3,4);; curry plus 3 4;; (* Folding Functions over Lists *) let rec sumlist list = match list with [ ] -> 0 | x::xs -> x + sumlist xs;; sumlist [2;3;4];; let rec prodlist list = match list with [ ] -> 1 | x::xs -> x * prodlist xs;; prodlist [2;3;4];; (* Folding *) let rec fold_left f a list = match list with [] -> a | (x :: xs) -> fold_left f (f a x) xs;; let rec fold_right f list b = match list with [ ] -> b | (x :: xs) -> f x (fold_right f xs b);; (* Folding *) let sumlist list = fold_right (+) list 0;; sumlist [2;3;4];; let prodlist list = fold_right ( * ) list 1;; prodlist [2;3;4];; (* Encoding Recursion with Fold *) let rec append list1 list2 = match list1 with [ ] -> list2 | x::xs -> x :: append xs list2;; let append list1 list2 = fold_right (fun x y -> x :: y) list1 list2;; append [1;2;3] [4;5;6];; (* Combining Lists of Functions *) let rec complist flist = match flist with [ ] -> (fun x -> x) | f::fs -> compose f (complist fs);; complist [( - ) 1; ( * ) 3; plus_two] ;; complist [( - ) 1; ( * ) 3; plus_two] 5;; (* Combining Lists of Functions *) let rec complist flist = match flist with [ ] -> (fun x -> x) | f::fs -> compose f (complist fs);; (* Repeating n Times *) let rec repeat_for n f x = (print_int n; match n with 0 -> x | _ -> f (repeat_for (n - 1) f x));; repeat_for 8 (fun x -> x * 2) 1;; let rec iter n f x = match n with 0 -> x | _ -> iter (n - 1) f (f x);; iter 8 (fun x -> x * 2) 1;; (* Mapping *) let rec inclist list = match list with [ ] -> [ ] | x :: xs -> (1 + x) :: inclist xs;; inclist [2;3;4];; let rec doublelist list = match list with [ ] -> [ ] | x :: xs -> (2 * x) :: doublelist xs;; doublelist [2;3;4];; (* Recall Map *) let fib5 = [5;3;2;1;1] let rec map f list = match list with [] -> [] | (h::t) -> (f h) :: (map f t);; map plus_two fib5;; (* Mapping *) let inclist = map ((+) 1);; inclist [2;3;4];; let doublelist = map (( * ) 2);; doublelist [2;3;4];; (* Map from Fold *) let map f list = fold_right (fun x y -> f x :: y) list [ ];; map ((+)1) [1;2;3];; (* Related Fuction: Zip *) let rec zip list1 list2 = match (list1,list2) with ([ ], _) -> [] | (_, [ ]) -> [] | (x::xs, y:: ys) -> (x,y)::zip xs ys;; zip [1;2;3] [4;5;6];; (* Zipwith *) let rec zipwith f list1 list2 = match (list1,list2) with ([ ], _) -> [] | (_, [ ]) -> [] | (x::xs, y:: ys) -> f x y ::zipwith f xs ys;; zipwith (+) [1;2;3] [4;5;6];; zipwith (fun x y -> (x,y)) [1;2;3] [4;5;6];; (* Zip from Zipwith *) let zip = zipwith (fun x y -> (x,y));; zip [1;2;3] [4;5;6];; (* Problem 1: Write a function flipuc that flips the arguments to an uncurried function, using just curry, flip and uncurry *) let flipuc f = uncurry (flip (curry f));; let cons (x,xs) = x::xs;; let snoc = flipuc cons;; snoc(snoc ([1],2),3);; (* Problem 2: Write a function that has type ('a -> 'b) -> 'a * 'c -> 'b *) let app_fst f (a,b) = f a;; app_fst ((+) 1) (3, 7);; app_fst ((+) 1) (4, "hi");; (* Problem 3 : Use fold_right to write a function that takes a list and returns it. *) let listId list = fold_right (fun x xs -> x::xs) list [];; listId [1;2;3];; (*Problem 4 Use fold_right to write a function to remove all negative elements from a list *) let gezero list = fold_right (fun x xs -> if x >= 0 then x::xs else xs) list [ ];; gezero [1;0;3;-5;7;-2];;