Lambdas and composition

Contents
Lambdas
Composition
Point-free style
Where it hurts

Lambdas

A lambda is a function without a name. The backslash stands in for the Greek letter, the arguments follow, and an arrow separates them from the body:

map (\x -> x * x) [1,2,3] -- [1,4,9] filter (\s -> length s > 3) ["cat","horse"] -- ["horse"] zipWith (\a b -> a * b) [1,2] [10,20] -- [10,40]

Use one when the function is short and used once. As soon as the same lambda appears twice, or it grows past one line, give it a name in a where block.

Composition

The dot operator joins two functions into one. It reads right to left, so the rightmost function runs first:

oddLength = odd . length oddLength "abc" -- True shout = map toUpper . filter (/= ' ') shout "hi there" -- "HITHERE"

Composition is associative, so f . (g . h) and (f . g) . h are the same function. That is what lets a long pipeline be split across lines without changing its meaning.

Point-free style

When the last argument appears on both sides, it can be dropped. The result is called point-free, and it is a matter of taste, not of correctness:

-- with the argument named total xs = sum (map (*2) xs) -- the same function, point-free total = sum . map (*2)

The second version says what the function is rather than what it does to an argument. It reads well for three or four steps and badly beyond that.

Where it hurts

Point-free style fails when an argument is used twice or in an unusual position. Fighting the compiler to remove a name is a sign that the name should stay:

-- clear describe x = show x ++ " (" ++ show (x * 2) ++ ")" -- unreadable, do not do this describe = ((++) . (" (" ++) . show . (*2) . (")" ++)) . show

The second line is technically valid and practically hostile. Write the version a colleague can read at two in the morning.

Next: Type classes

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
Banner image

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: