Haskell Hero

Interaktivní učebnice pro začínající Haskellisty

Lambda abstrakce

Proč výrazy s lambdou?

Příklad

Definujte funkci zvetsiSeznam :: [Integer] -> [Integer], které dáme jako argument seznam celých čísel a ona každé číslo zdvojnásobí a přičte k němu pět.

zvetsiSeznam [1,2,5]  ~>*  [1*2+5, 2*2+5, 5*2+5]  ~>*  [7,9,15]


Nejjednodušší bude použít funkci map, které dáme jako první argument funkci, která svůj argument zdvojnásobí a přičte k němu pět. Zadefinujme si tedy tuto pomocnou funkci:

zvetsi   ::  Integer -> Integer
zvetsi x  =  x*2+5
Následně můžeme definovat i námi požadovanou funkci:
zvetsiSeznam   ::  [Integer] -> [Integer]
zvetsiSeznam s  =  map zvetsi s
A jsme hotovi. Pokud bychom ale funkci zvetsi k ničemu jinému nepotřebovali, je její definování tímto způsobem docela zbytečné. Můžeme totiž použít tzv. anonymní funkce.

Výrazy s lambdou

Výrazy s lambdou nejvíce oceníme v situacích, kdy potřebujeme rychle definovat funkci, kterou použijeme pouze na jednom místě. Například funkce, která zdvojnásobuje svůj argument, může vypadat následovně:

\x -> 2 * x
Toto je anonymní unární funkce, do které vhodíme číslo a vypadne z ní jeho dvojnásobek. Aneb "Vezmi x a udělej z něj 2 * x."

Binární funkce, do které hodíme dvě čísla a ona nám je sečte, může vypadat například takto:

\x y -> x + y
Aneb "Vezmi x a y a udělej z nich x + y."

Příklady vyhodnocení:

(\x -> 2 * x)   5    ~>  2 * 5  ~>  10
(\x y -> x + y) 3 5  ~>  3 + 5  ~>  8

Funkci z předchozího odstavce můžeme tedy definovat pomocí anonymní funkce takto:

zvetsiSeznam   ::  [Integer] -> [Integer]
zvetsiSeznam s  =  map (\x -> x*2+5) s


Pomocí lambdy můžeme i jiným zápisem definovat funkce curry a uncurry.

curry   g  =  \x y   -> g (x,y)
uncurry f  =  \(x,y) -> f x y
Z tohoto zápisu je i lépe vidět častý způsob použití těchto dvou funkcí. Například můžeme zadefinovat funkci fst pomocí funkce const a naopak.
fst    =  uncurry const
const  =  curry fst