F Sharp Programming/Higher Order Functions

A higher-order function is a function that takes another function as a parameter, or a function that returns another function as a value, or a function that does both.

Familiar Higher Order Functions
To put higher order functions in perspective, if you've ever taken a first-semester course on calculus, you're undoubtedly familiar with two functions: the limit function and the derivative function.

The limit function is defined as follows:
 * $$ \lim_{x \to p}f(x) = L $$

The limit function,, takes another function   as a parameter, and it returns a value   to represent the limit.

Similarly, the derivative function is defined as follows:
 * $$deriv(f(x))=\lim_{h\to 0}{f(x+h)-f(x)\over h}=f'(x)$$

The derivative function,, takes a function   as a parameter, and it returns a completely different function   as a result.

In this respect, we can correctly assume the limit and derivative functions are higher-order functions. If we have a good understanding of higher-order functions in mathematics, then we can apply the same principles in F# code.

In F#, we can pass a function to another function just as if it were a literal value, and call it just like any other function. For example, here's a very trivial function:

In F# notation,  has the following type:

In other words,  takes a function , where   must take an   and return any generic type. Our function  has the return type   because we don't know the return type of   in advance.

These functions have the following types:

Unlike many other languages, F# makes no distinction between functions and values. We pass functions to other functions in the exact same way that we pass ints, strings, and other values.

Creating a Map Function
A map function converts one type of data to another type of data. A simple map function in F# looks like this:

This has the type. In other words,  takes two parameters: an item 'a, and a function that takes an   and returns a  ; map returns a.

Let's examine the following code:

These functions have the following signatures:

The  function passes a datatype   and a function with the signature  ; this means the placeholders   and   in the map function both become  s.

The  function passes a datatype   and a function , and   predictably returns a.

The  function passes a datatype   and a function , and   returns a   just as we expect.

Since our generic code is typesafe, we would get an error if we wrote: Because the  constrains our function to a type , but the   function has the type  , so it's obviously incorrect.

The Composition Function ( operator)
In algebra, the composition function is defined as, denoted f o g. In F#, the composition function is defined as follows: Which has the somewhat cumbersome signature.

If I had two functions:
 * f(x) = x^2
 * g(x) = -x/2 + 5

And I wanted to model f o g, I could write:

Note that  doesn't return a value, it returns another function whose signature is.

There's no reason why the compose function must be limited to numbers. Since it's generic, it can work with any datatype, such as s,  s,  s, and so on.

There also exists the  operator, which similarly performs function composition, but in reverse order. It is defined as follows:

This operator's signature is as follows:.

The advantage of doing composition using the  operator is that the functions in the composition are listed in the order in which they are called.

This first applies  and then applies   on the result.

The Operator
The pipe forward operator,, is one of the most important operators in F#. The definition of the pipe forward operator is remarkably simple:

Let's take 3 functions:

Let's also say we had a complicated function that squared a number, added five to it, and converted it to a string? Normally, we'd write this: We can improve the readability of this function somewhat using the pipe forward operator:

is piped to the  function, which is piped to   method, and finally to the   method.

Anonymous Functions
Until now, all functions shown in this book have been named. For example, the function above is named. F# allows programmers to declare nameless, or anonymous functions using the  keyword.

Anonymous functions are convenient and find a use in a surprising number of places.

A Timer Function
The  function has the type. This program prints: Elapsed Time: 1 fib 5: 5 Elapsed Time: 5 fib 30: 832040
 * Note: the actual duration to execute these functions vary from machine to machine.

Currying and Partial Functions
A fascinating feature in F# is called "currying", which means that F# does not require programmers to provide all of the arguments when calling a function. For example, let's say we have a function:

takes two integers and returns another integer. In F# notation, this is written as

We can define another function as follows:

The  function calls the   function with one of its parameters, so what is the return value of this function? That's easy:  returns another function, which is waiting for the rest of its arguments. In this case, addFive returns a function that takes an  and returns another , denoted in F# notation as.

You call  just in the same way that you call other functions:

How Currying Works
The function  has the type. F# uses the slightly unconventional arrow notation to denote function signatures for a reason: arrows notation is intrinsically connected to currying and anonymous functions. Currying works because, behind the scenes, F# converts function parameters to a style that looks like this:

The type  is semantically equivalent to.

When you call  with no arguments, it returns   (or equivalently  ), another function waiting for the rest of its arguments. Likewise, when you supply one argument to the function above, say 5, it returns, another function waiting for the rest of its arguments, with all occurrences of x being replaced by the argument 5.

Currying is built on the principle that each argument actually returns a separate function, which is why calling a function with only part of its parameters returns another function. The familiar F# syntax that we've seen so far,, is actually a kind of syntactic sugar for the explicit currying style shown above.

Two Pattern Matching Syntaxes
You may have wondered why there are two pattern matching syntaxes:

Both snippets of code are identical, but why does the shortcut syntax allow programmers to omit the  parameter in the function definition? The answer is related to currying: behind the scenes, the F# compiler converts the  keyword into the following construct:

In other words, F# treats the  keyword as an anonymous function that takes one parameter and returns one value. The  function actually returns an anonymous function; arguments passed to   are actually applied and evaluated by the anonymous function instead.