(* CS:3820, Fall 2018 *) (* Cesare Tinelli *) (* The University of Iowa *) (* F# examples seen in class *) (* functions as values: closures *) let a = 10 let f x = x + a let f = fun x -> x + a // true syntax for declaration above let g = fun x -> 2 * x let p = (f, g) let l = [f; g] ((List.head l) 8) ((List.last l) 8) (* Higher-order functions *) let m = 4 let h x = x + m let h = fun x -> x + m h 10 let make_incr m = (fun x -> x + m) let add6 = make_incr 6 add6 10 let add m n = m + n // true syntax for add let add = fun m -> (fun n -> m + n) let add1 = add 1 add1 5 add 1 5 (add 1) 5 let add1 = (+) 1 let applyTwice f x = f (f x) applyTwice (add 10) 3 applyTwice (fun x -> x + 5) 3 let compose f g x = f (g x) let square x = x * x compose add1 square 3 let add2 = compose add1 add1 add2 3 let (<*>) f g x = f (g x) (add1 <*> square) 3 ((fun x -> x + 1) <*> (fun x -> x * x)) 3 let twice f = f <*> f (twice (add 1)) 3 // pipe function let (|>) x f = f x 4 |> square |> (add 1) // map combinator let rec map f l = match l with | [] -> [] | h :: t -> (f h) :: (map f t) map (add 1) [1; 2; 3] map square [1; 2; 3] map ((+) " ") ["a"; "b"; "c"] map (fun x -> x + " ") ["a"; "b"; "c"] // foldLeft combinator let rec foldLeft f acc l = match l with | [] -> acc | h :: t -> foldLeft f (f acc h) t let add x y = x + y (* foldLeft add 0 (3::2::1::[]) --> foldLeft add (add 0 3) (2::1::[]) --> foldLeft add 3 (2::1::[]) --> foldLeft add (add 3 2) (1::[]) --> foldLeft add 5 (1::[]) --> foldLeft add (add 5 1) [] --> foldLeft add 6 [] --> 6 *) foldLeft (+) 0 [1; 2; 3; 4] foldLeft (*) 1 [1; 2; 3; 4] foldLeft (+) "" ["1"; "2"; "3"; "4"] foldLeft (+) "" ["1"; "2"; "3"; "4"] foldLeft (@) [] [[1; 2]; [3; 4]; [5]] foldLeft (+) "" (map (fun x -> x + " ") ["1"; "2"; "3"; "4"]) ["1"; "2"; "3"; "4"] |> (map (fun x -> x + " ")) |> (foldLeft (+) "") // forAll combinator let rec forAll p l = match l with | [] -> true | h :: t -> (p h) && (forAll p t) forAll (fun x -> x = 0) [0; 1; 0] forAll (fun x -> x = 0) [0; 0; 0] forAll (fun x -> x > 0) [1; 20; 4] forAll ((<=) 0) [1; 20; 4] // filter combinator let rec filter p l = match l with | [] -> [] | h :: t -> if (p h) then h :: (filter p t) else filter p t filter (fun x -> x > 0) [1; 20; -4; 5; 0] filter (fun x -> x > 0) [1; 20; -4; 5; 0] |> map square filter (fun x -> x > 0) [1; 20; -4; 5; 0] |> map (square <*> square) |> forAll (fun x -> x > 10)