let double x = 2 * x;; let square x = x * x;; (* Notice the pattern of invoking a function twice... why not generalize it? *) let quad x = double (double x);; let fourth x = square (square x);; (* higher order function -- passing a function as an argument, then applying it *) let twice f x = f (f x);; (* currying calls to twice. What is initially returned from calling twice with double is a function that expects an integer and calls double two times *) let quad x = twice double x;; let fourth x = twice square x;; (* Intead of currying, we could pass a single tuple value with two components. Here the higher order function is part of a tuple using a variety of ways of processing (breaking apart) the tuple *) let twice (f, x) = f (f x);; let quad x = twice (double, x);; let fourth x = twice (square, x);; let twice pair = let (f, x) = pair in f (f x);; let twice pair = ((fst pair) ((fst pair) (snd pair)));; let twice pair = let f = (fst pair) and x = (snd pair) in f (f x);; let twice pair = match pair with | (f,x) -> f (f x);; (* Let's look more at currying. This is actually what is happening implicitly with let twice f x = f (f x);; and, in fact, with any function with "more than one" parameter. All OCaml functions only accept one parameter, but syntax shortcuts allow us to ignore that this is happening *) let twice f = fun x -> f (f x);; (* Here's another example where a function with two parameters is actually two functions, each with one parameter, that are being curried *) let max x y = if (x > y) then x else y;; (* This is the view making the currying explicit *) let max x = fun y -> if (x > y) then x else y;; (* Here we have three parameters, so there are actually three functions *) let max f x y = if (f x) > (f y) then x else y;; let max f = fun x -> fun y -> if (f x) > (f y) then x else y;; (* Here we're naming the intermediate functions that are created during the currying above maxabs is max called with the abs function as its argument *) let maxabs = (max abs);; maxabs (-3) (-5);; (* maxabs3 is maxabs called with 3 as its first parameter, the function returned will always compare the absolute value of the number supplied with the absolute value of 3 *) let maxabs3 = maxabs 3;; maxabs3 (-5);;