In most languages a function is something you call. In functional programming a function is also a value β you can store it in a variable, pass it into another function, and get one back as a result. A higher-order function is exactly the function that does one of those last two things. This guide explains what a higher-order function is, why map, filter and fold are the classic examples, how they replace loops, and how they look in Haskell.
The short definition
A higher-order function is a function that takes one or more functions as arguments, returns a function as its result, or both. A function that does neither β it only takes and returns plain values like numbers or strings β is called a first-order function. The "higher-order" name simply means it operates on functions the way an ordinary function operates on data.
This only works in a language where functions are first-class values: things you can name, pass around and return, just like an integer. Haskell, JavaScript, Python, Swift and many others treat functions this way, which is what makes higher-order functions possible.
The three classics: map, filter and fold
Almost every functional codebase leans on three higher-order functions. Each one takes a function as an argument and applies it across a collection:
- **map** applies a function to every element of a list and gives back a new list of the results. `map (+1) [1,2,3]` gives `[2,3,4]` β the function `(+1)` is the argument.
- **filter** keeps only the elements for which a function returns true. `filter even [1,2,3,4]` gives `[2,4]` β here `even` is the function you pass in.
- **fold** (also called reduce) collapses a list down to a single value by combining elements two at a time. `foldr (+) 0 [1,2,3]` adds them up to `6` β the combining step `(+)` is the function argument.
In each case you supply the small piece of logic β increment, "is even", add β and the higher-order function handles the walking-over-the-list part. You describe what to do to each element, not the bookkeeping of how to step through them.
How they replace loops
In an imperative language you might write a loop with a counter, an accumulator, and an explicit index. The same intent expressed with a higher-order function disappears into a single line, because the iteration is already baked into map or fold. That is why purely functional code, which avoids mutable loop counters, leans so heavily on these functions and on recursion β the two cover the work that loops do elsewhere. List comprehensions are often a readable shorthand for the same map-and-filter combination.
Returning a function: where it gets powerful
The other half of the definition β functions that return functions β is just as common. A function can build and hand back a new, specialised function. A classic example is a "multiplier maker": you give it a number and it returns a function that multiplies its input by that number. Call it with 3 and you get back a "times three" function you can then use like any other. The maker is higher-order because its result is itself a function.
In Haskell this is woven into the language through currying: every function of several arguments is really a chain of one-argument functions, each returning the next. That is why map (+1) works β (+1) is the addition function with one argument already supplied, returning a function that still expects the other. Partial application like this is higher-order functions at work, often without you noticing.
Higher-order functions in Haskell
Haskell makes the idea explicit in its type signatures. The type of map is written map :: (a -> b) -> [a] -> [b]. Read it left to right: the first argument (a -> b) is itself a function β that is the higher-order part β followed by a list of a, producing a list of b. The arrows make it visible on the page that a function is being passed in. The same pattern appears in filter :: (a -> Bool) -> [a] -> [a] and across the standard library.
You often pass these functions inline as lambdas β small anonymous functions written with a backslash, like map (\x -> x * x) [1,2,3] to square each element. Whether you pass a named function, an operator section like (*2), or a lambda, it is the same mechanism: a function travelling as a value into a higher-order function.
Why they matter
Higher-order functions let you factor out the common shape of a computation β "do something to every element", "keep the ones that match", "combine them all" β and reuse it with different logic plugged in. That means less repeated boilerplate, code that reads closer to its intent, and small, testable pieces of logic you can compose. They are the building block on top of which much of functional programming is expressed, and combined with Haskell's lazy evaluation they even let you map and filter over lists that are conceptually infinite.
The honest trade-offs
Higher-order functions take some getting used to: reading foldr or a chain of map . filter is a skill, and deeply nested lambdas can become hard to follow. Passing functions around can also make a stack trace less obvious when something goes wrong. The payoff β far less repetitive iteration code and logic you can recombine β is why they have spread well beyond functional languages into everyday JavaScript, Python and Swift. Used with restraint, they make code shorter and clearer; overused, they can obscure it like any other tool.
Frequently asked questions
What is a higher-order function in simple terms?
A higher-order function is a function that takes another function as an argument, returns a function as its result, or both. Instead of working only on plain data like numbers and strings, it works on functions. Classic examples are map, filter and fold, which each take a small function and apply it across a list.
Is map a higher-order function?
Yes. map takes a function as its first argument and applies it to every element of a list, returning a new list of the results. Because one of its arguments is itself a function, map is a textbook higher-order function β and so are filter and fold for the same reason.
What is the difference between a higher-order and a first-order function?
A first-order function only takes and returns ordinary values, such as numbers or strings. A higher-order function takes one or more functions as arguments, or returns a function, or both. The difference is whether the function operates on data alone or also on other functions.
Do higher-order functions only exist in Haskell?
No. They exist in any language that treats functions as first-class values β values you can store, pass and return. Haskell, JavaScript, Python, Swift and many others all support them. Haskell makes the idea especially visible through its type signatures and currying, but the concept is widespread.
Recommended
A Linux box to build and run your Haskell code
Trying these higher-order functions for real β loading them into GHCi, building a project with map and fold, then running it β is smoother on a proper Linux machine than a laptop. A cloud server gives you full control to install GHC and a Haskell toolchain in a clean environment and reach it over SSH. Infomaniak β a Swiss, privacy-respecting provider β offers cloud servers for exactly that.
[See Infomaniak Cloud β](https://coldwa.st/go/cloud.html)
Affiliate link β it supports these free guides.
Browse more clear explainers in our guides index.
Originally published on coldwa.st.





