In this unit, we are learning several new ways how to compose functions into more interesting functions. The key concept here is called higher order functions. In fact, functional languages treat functions as first class values. That means like any other value, a function can be passed as a parameter and returned as a result. And we'll see that this provides a flexible way to compose programs. Functions that take other functions as parameters or that you turn them as results are called higher order functions. So let's start with an example, take the sum of the integers between a and b. So we have a function sumInts lower bound a, upper bound b. And we have a recursive definition, if a greater than b then the interval is empty and the sum is 0. Otherwise we take a + sumInts(a + 1, b), good so far. Now, let's take the sum of the cubes of all the integers between a and b. So the cube function would be just like the square function only three times x multiplied. So sumCubes, you could write this, if a > b then 0 as cube(a) + sumCubes(a + 1, b). Okay, now let's take the sum of the factorials of all the integers between a and b. So we could write a function sumFactorials from a and b. And then it's the same thing here except where we wrote cube we write fact for factorial of a plus sumFactorial(a + 1, b). So I assume here that fact is the factorial functions. Now, a mathematician would get bored very quickly and they would say well, these are all special cases of what we know is the sum functions. And here's the way mathematicians would write it. So it's a big sigma. And you say the lowest the start value is a, the end value is b. And we take essentially the sum of all the values of f of n, where n goes from a to b. Can we do the same in programming? Can we factor out the common pattern? So what varies in these things, well, the thing that varies is the functions that I pass into the summation function. So what we can do in function programming is we can make a parameter that is a function. So here we have a new definition of sum that takes now a function f, and a lower bound a and an upper bound b. And it has exactly the same pattern as before, only it uses the function parameter f at this position here. So, if the interval is not empty then we take f of the lower bound and then we go on with sum of f and a plus one and b. So once we have that, we can write our sumFunctions in this way. We can say well, sumInts is the sum of the identity id a and b. SumCubes is the sum of the cube function and a and b. And sumFactorials is the sum of the factorial function and a and b. Where the id function is just x, the cube function is x times, x times, times x. And the factorial function is the usual definition of factorial. So what we've seen here is a new type, Int to Int, and that type is the type of a function. So generally the type A arrow B is the type of a function that takes an argument of type A and returns a result of type B. So Int to Int is a type of functions that map integers to integers. So generally passing functions as parameters leads to the creation of many small functions. And sometimes it's tedious to have to define and invent a name for all these functions using a def. Compare the to strings, we do not need to define a string using def instead of def string equals abc printInstring, we can directly right printIn (abc), because strings exist as literals. Analogously, we would like a literal for a function that let us write a function without giving it a name. And these liberals exist. They're called anonymous functions. So for instance, here's a function that raises its argument to a cube. It takes a parameter x of type Int and returns x times, x times, times x. So that functions doesn't have a name. We haven't given it a name. That's why it's an anonymous function. x : Int is the parameter, and x * x * x is the body. The type of the parameter can be omitted if it can be inferred by the compiler from the context. And if there are several parameters, they are separated by commas. So for instance, x : Int, y : Int arrow x + y would be the function that sums it's two arguments, x and y. Anonymous functions are very convenient sometimes, but they're not essential. In fact, we can always express an anonymous function like this one here using a def. So instead of writing the anonymous function, we give it a name. Call it f here, but it could be really be any name. Write the same parameters, the same body, and then follow that by f and put it in braces to make it a block. So that's exactly the same as the anonymous function. The name here doesn't matter because it's inside the blocks and nobody can refer to it from the outside. Because anonymous functions expand like this to something that we know already, we can therefore say that anonymous functions are syntactic sugar. Syntactic sugar means it makes life nicer, but it's not essential. So with anonymous functions, we can now write sums in a shorter way. So for instance, sumInts would be simply sum functions where the function that we pass is the identity. It takes an x gives us back the x. And the bounds are a and b. And sumCubes would be the function that calls some with an anonymous function. And the anonymous function takes an x and returns x* x * x. What you've seen in both of these examples is that we don't need a type for these parameters. That's because essentially the compiler knows that the sum function expects a function from Int to Int so it can infer that the parameter must necessarily be of type Int. So here's an exercise for you. The sum function uses linear recursion. That means the stack grows as the sum function sums up its operands. Can you write a tail-recursive version? So I'll give you a hint. Here's the general scheme. And what you should do is replace the triple question marks with expressions of your own. Okay, so let's see how we would write the body of loop. It essentially follows the scheme that we've seen before. So we say if a is greater than b, then we have the case where essentially we can return what we already computed. And the idea is what we computed we put in this accumulator which we call acc. So acc is essentially the intermediate result. So we return acc. And if not, then we go on with the loop. So the loop takes a new lower bound that would be a + 1. And it takes an accumulator of the things that we have already summed up. So that would be the old accumulator plus F of a. The initial call, so how do we set off the iteration where we call loop with the original lower bound a. And what is our accumulator? Well, it's a zero value for the sum, so it's zero.