===== Higher-order functions ===== In our previous examples, we have seen functions such as ''(+)'' or ''(*)'' which are passed as parameter to other functions, e.g. ''foldr''. //A function which expects another function as parameter is called a **higher-order function**//. One distinctive functional programming trait relies on defining and using higher-order functions. Haskell makes this programming style very natural. Functions can be defined in several ways, e.g. f x = x + 1 as **anonymous functions**: f = \x -> x + 1 (which is read //"lambda x ..."//) or using **pattern matching**: f 0 = 1 f 1 = 2 f 2 = 3 ==== Currying ==== Consider the following function definitions: f1 x y = x + y f2 x = \y -> x + y f3 = \x -> \y -> x + y f4 = \x y -> x + y Read syntactically: * the first function expects two parameters and returns their additions * the second function **returns a function which adds y to x**. For instance ''(f2 4)'' is a function which adds ''4'' to an integer * the third function is similar to the previous one, but defined as an anonymous function * the fourth function is an anonymous function definition with two parameters **There is no conceptual or functional difference between //any// of the above definitions**. From a //Haskell compiler's view// all function definitions look exactly as the third one. For instance, ''(f1 1)'' is a correct function call which will return a function adding ''1'' to its parameter. ''(f1 1)'' is called a **functional closure**, because it creates (closes) a context in which the first parameter is equal to the value ''1''. At the same time, the function call ''((f1 1) 2)'' is correct, returns ''3'', and is equivalent to ''(f1 1 2)''. More generally, functions defined as ''f2'' or ''f3'' are called **curried (or curry) functions** (in honor of Haskell Curry, a mathematician which contributed to functional programming) --- they receive parameters //in turn//. The other definitions are called **uncurried**. We again stress that, in Haskell, there is no difference between curried and uncurried functions. This is **not the case** in other functional languages, e.g. Lisp, Scheme. ==== Other higher-order functions ==== Imagine we want to do a certain computation on each member of a list, individually. Let's say, double each element. If we think functionally, we want to take a list ''[a,b,c, ...]'', a function ''f'', and build the list: [f a, f b, f c, ...] It turns out we can write such a function relying on fold: pp_map f = foldr (\x y->(f x):y) [] There is also a shorter way to write ''pp_map'': pp_map f = foldr ((:).f) [] In the expression ''(:).f'', ''.'' (the dot) stands for functional composition. Consider the anonymous function: \x->x+1 which takes a parameter ''x'' and returns its natural successor. We can compose it as follows: (\x -> 2*x).(\x->x+1) to obtain the function ''\x -> 2*(x+1)''. In general, the function call ''(f.g) x'' is equivalent to ''f (g x)''. To understand ''(:).f'' let us write the cons ''(:)'' as an anonymous function: \h t -> h:t Hence, the following expressions are equivalent: ((:).f) ((\h t -> h:t).f) ((\h->\t->h:t).f) (\t->(f h):t) A natural mistake is to consider ''((:).f)'' as invalid, since it receives two parameters, and we cannot compose such a function with one receiving only one parameter. However, every function in Haskell receives one parameter and returns **a value** (which can be a function or a primitive value). There are other examples of useful higher-order functions. We illustrate them using examples, which you should test out: filter (>3) [1,2,3,4,5,2] zipWith (+) [1,2,3] [3,2,1] Guess what each function does, by testing it on several lists. ===== Practice =====