Currying and partial application

Contents
One argument at a time
Partial application
flip and sections
Why it matters

One argument at a time

A function of two arguments is a function of one argument that returns a function. The arrow is right associative, so the signature below is the same as Int -> (Int -> Int):

add :: Int -> Int -> Int add a b = a + b -- add :: Int -> (Int -> Int)

Applying add to one number does not fail. It returns a function waiting for the second number.

Partial application

Supplying fewer arguments than a function expects is called partial application, and the result is a perfectly ordinary function:

addFive = add 5 addFive 3 -- 8 map (add 5) [1,2,3] -- [6,7,8]

This is why map takes a function and a list rather than a lambda: a half-applied function is usually exactly the function you need.

flip and sections

Order matters when you partially apply. flip swaps the first two arguments, and a section writes an operator with one side left open:

flip subtract 10 3 -- 7 map (10 -) [1,2,3] -- [9,8,7] map (subtract 10) [1,2,3] -- [-9,-8,-7]

A left section fixes the left operand, a right section fixes the right one. The two lines above look similar and produce opposite results, which is the usual reason for a subtle bug.

Why it matters

Currying lets a general function become a specific one without defining anything new. A validator, a formatter, or a comparison arrives half-built and gets finished at the call site:

isLongerThan :: Int -> String -> Bool isLongerThan n s = length s > n filter (isLongerThan 3) ["cat", "horse", "ox"] -- ["horse"]

The same trick scales to foldr and traverse later. Learn to read a function as a chain of one-argument steps and the rest of the course gets easier.

Next: Operators, sections, and fixity

Article author: Arthur Isaev

Related articles
Haskell
Haskell course: zero to hero in 50 lessons
What is Haskell and why it matters
Install the toolchain with GHCup
GHCi: the interactive shell
Your first program
Values with let and where
Types and type signatures
Functions and application
Currying and partial application
Operators, sections, and fixity
if, guards, and pattern guards
case expressions
Pattern matching
Tuples
Lists
Ranges and enumeration
List comprehensions
Recursion replaces loops
map, filter, and foldr
Lambdas and composition
Type classes
Parametric polymorphism
Maybe and null safety
Either and recoverable errors
data: product types
data: sum types
Records
newtype and type synonyms
Recursive data: binary trees
Functor
Applicative
Monad
do notation
IO and purity
Files and IO
Modules and imports
Cabal projects
Dependencies
Testing with HUnit
Property testing with QuickCheck
Laziness and infinite lists
Strictness and space leaks
Folds
Monoids
Traversable
Monad transformers
Errors and exceptions
Concurrency
Parsing with Megaparsec
Capstone: a todo CLI
Hero roadmap: the whole course on one page

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: