09 March 2026

Higher Order Functions in F#

One of the things about F# that I am still trying to better understand is the concept of treating functions as “first class citizens”, especially when it comes to passing functions to other functions or having functions return another function. Functions that can take another function as an argument or return a function as a result are called higher-order functions.

Coming from more mainstream programming languages, this idea really makes my head explode!

Here’s a simple example. Suppose we define a function applyFunction as follows:

> let applyFunction funct a b = funct a b;;
val applyFunction: funct: ('a -> 'b -> 'c) -> a: 'a -> b: 'b -> 'c

In this example, applyFunction takes three arguments:

  1. A function funct that takes two generic arguments and returns a generic value.

  2. A generic argument 'a.

  3. A generic argument 'b.

It then applies the function funct to 'a and 'b, returning the generic value 'c.

Let’s see how we can use this in practice. First, let’s define a function that takes two arguments and returns a value:

> let add x y = x + y;;
val add: x: int -> y: int -> int

The type signature of add matches that of funct above which means we can now pass add, along with two other arguments, to applyFunction:

> applyFunction add 4 5;;    
val it: int = 9

applyFunction accepts the function add and the two integers 4 and 5 and applies add to them returning 9.

Like we did in the previous post, we can also use partial application on applyFunction to define a new function:

> let newAdd = applyFunction add;;
val newAdd: (int -> int -> int)

> newAdd 4 5;;
val it: int = 9

newAdd now takes two integers and returns another. In practice, is this how we would define newAdd? Probably not since we could have more easily done:

> let newAdd = add;;
val newAdd: (int -> int -> int)

However, I think this line of application does make sense when we’re working with anonymous functions, or functions that have no name (also referred to as lamdas). For example:

> let newAdd = applyFunction (fun x y -> x + y);;
val newAdd: (int -> int -> int)

> newAdd 3 4;;
val it: int = 7

Here, we’re combining the concepts of anonymous functions with partial applcation. Instead of passing a defined function, such as add to applyFunction, we’re passing anonymous function fun x y -> x + y. This works because the anonymous function has the same type signature expected by applyFunction: 'a -> 'b -> 'c.

For a more practical example of how all of this comes together, let’s take a look at Exercise 7.1 in “F# in Action” which has us build a simple calculator.

Let’s define a new function, calculate, similar to applyFunction:

> let calculate operation x y = operation x y;;
val calculate: operation: ('a -> 'b -> 'c) -> x: 'a -> y: 'b -> 'c

Because calculate is a higher-order function, we can pass to it various other anonymous functions that represent basic mathematical operations:

> calculate (fun a b -> a + b) 2 3;;
val it: int = 5

> calculate (fun a b -> a - b) 10 8;;
val it: int = 2

We can get a little bit fancier by passing both an operation as well as a description of the action we are taking as a tuple so that we can return a string that describes what we are doing:

> let calculate (operation, action) x y =                   
-     let answer = operation x y                            
-     sprintf $"%i{x} %s{action} %i{y} equals %i{answer}";; 
val calculate:
  operation: (int -> int -> int) * action: string ->
    x: int -> y: int -> string

We can then call calculate as follows:

> let result = calculate (( fun x y -> x / y ), "divided by") 10 2;;
val result: string = "10 divided by 2 equals 5"

Putting this all together, we can create a simple calculate.fsx script:

let calculate (operation, action) x y =
    let answer = operation x y
    sprintf $"%i{x} {action} %i{y} equals %i{answer}"

printfn "Enter the first number: "
let x = System.Console.ReadLine() |> int
printfn "Enter the second number: "
let y = System.Console.ReadLine() |> int

printfn "Enter an operation:"
printfn "    1. Add"
printfn "    2. Multiply"
printfn "    3. Subtract"
printfn "    4. Divide"
printfn "Enter your choice: "
let choice = System.Console.ReadLine()

let operation =
    match choice with
    | "1" -> ((fun a b -> a + b), "plus")
    | "2" -> ((fun a b -> a * b), "multiplied by")
    | "3" -> ((fun a b -> a - b), "minus")
    | "4" -> ((fun a b -> a / b), "divided by")
    | _ -> failwith "Invalid choice"

let result = calculate operation x y
printfn "%s" result

which we can run via dotnet fsi calculate.fsx:

Enter the first number: 
10
Enter the second number: 
5
Enter an operation:
    1. Add
    2. Multiply
    3. Subtract
    4. Divide
Enter your choice: 
2
10 multiplied by 5 equals 50

Hopefully this example helps explain a bit more about what higher-order and anonymous functions are in F# and how they can be used in a simple example.

07 March 2026

Functions in F#

In learning about F#, one of the first things I had to come to terms with is that all F# functions have only one input and only one output.

This is a strange thing to understand when you’re allowed to write things like:

> let add x y = x + y;;

Even though it’s clear we’re returning one integer, it sure looks like we’re passing two arguments to add.

In reality, what’s happening becomes a bit clearer if we examine the function’s type signature:

val add: x: int -> y: int -> int

What this is saying is that add is a function that takes an int x and returns a function that takes int y and returns an int. Think of each arrow (->) as a function that takes the parameter from the left and returns the value to the right. This is called Currying, which is apparently named after the guy who invented Haskell.

Therefore, we can pass an integer, say 5, to the function add, and it will return another function which will take an interger y, add it to 5, and then return the result. If we name that new function add5, we can define it as follows:

> let add5 = add 5;;

which gives us the type signature of

val add5: (int -> int)

Calling add5 with another integer gives us the sum:

> add5 4;;
val it: int = 9

> add5 -7;;
val it: int = -2

We can also partially define other such functions by just passing the first argument to add:

> let add7 = add 7;;
val add7: (int -> int)

> let add10 = add 10;;
val add10: (int -> int)

> add7 4;;
val it: int = 11

> add10 20;;
val it: int = 30

Unsurprisingly, this concept is called Partial Application.

Update on 08 March 2026:

I didn’t want my post to imply that you can’t pass two or more arguments to a function. You certainly can:

> let add a b = a + b;;
val add: a: int -> b: int -> int

> add 4 9;;
val it: int = 13

In my very limited experience with F# so far, I don’t worry too much about currying; when I see a type signature that looks like val add: a: int -> b: int -> int, I’m still thinking about it as a function that takes two integers and returns one integer.

06 March 2026

Learning Functional Programming with F#

I'm not a programmer by profession or trade but I've always enjoyed working with computers and have dabbled in programming for as long as I've been able to access computers.  I've done the usual tour of duty using languages such as Basic, Python, Fortran, C, C#, D and Perl but I would not consider myself an expert in anything of them.  I can write simple imperative programs using control loops, if/else statements and generally know how functions, procedures or methods work in most of these languages.

For some reason though, I've never been able to wrap my head around functional programming and, until recently, never could properly define what it is.  Technically, I probably still can't but am getting to grips on what concepts functional programming entails and what behaviors it encourages.  So over the past few weeks, I've been trying to pick it up some using F#.  While most imperative languages, including C#, Perl and others can accommodate functional programming aspects, I thought I would try one of the ML-inspired languages to begin this journey.  I've already had .NET installed on my machine as I was learning C# so rather than install a whole new language or framework, I thought I would check out Microsoft's version of a functional language.  Haskell, OCaml and other languages still seem too esoteric and arcane to me but I know they have large followings devoted practitioners.

My original thought was to start by going through some functional programming books to begin my journey but the two most promising ones I could find "Grokking Functional Programming" and "Functional Programming in Scala" both use Scala as the language to convey functional programming concepts.  While both books state that the actual language doesn't really matter, I couldn't get past the unfamiliar syntax which distracted my ability to focus on the underlying theory of functional programming.  While it probably would have just been easier to install Scala and get on with it, I really didn't want to have both .NET and JDK on my machine.

For now, I am trying to go through Isaac Abraham's "F# in Action".  While it does espouse functional programming paradigms, it focuses more on introducing the reader to the fundamental aspects of the language itself which is what I really think I need.

I'm going to be sharing short snippets of what I learn and find interesting, more as a journal to remind myself of what I cover but would definitely appreciate any feedback, suggestions or comments from anyone who comes across these missives.