Haskell Hero

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

Užitečné funkce I

id

Unární funkce vracející argument v nezměněné podobě.

Definice

id  :: a -> a
id x = x

Příklad použití

id 5 ~> 5
id "ahoj" ~> "ahoj"
(id even) 3 ~> even 3 ~> False

Složitější příklad

comp     ::  Int -> (a -> a) -> a -> a
comp 0 _  =  id
comp n f  =  f . comp (n-1) f
Výraz comp n f x se vyhodnotí tak, že se na prvek x aplikuje n-krát funkce f. Funkce id zde funguje jako zastavující hodnota pro případ, že hodnota v prvním argumentu se zmenší na nulu.
comp 5 (+2) 10

~>*  ( (+2) . (+2) . (+2) . (+2) . (+2) . id ) 10
Operátor (.) je rozebrán v posledním odstavci.

const

Binární funkce vracející svůj první argument v nezměněné podobě.

Definice

const    :: a -> b -> a
const x y = x

Příklad použití

const 5 'q' ~> 5
const True (+8) ~> True
(const div "ffuu") 10 3 ~> div 10 3 ~> 3

Doplňující info

Výraz (const div "ffuu") 10 3 se vyhodnotí následovně:

  • Hugs začne vyhodnocovat zleva. To znamená, že se podívá na první věc zleva, což je funkce const.
  • Zjistí si, že funkce const je binární, to znamená, že ke svému plnému vyhodnocení potřebuje dva argumenty.
  • Jako první dvě věci, na které narazí, je funkce div a řetězec "ffuu".
  • Tyto dva argumenty jí k vyhodnocení stačí, takže se vyhodnotí podle definice na svůj první argument, což je div.
  • Funkce div se aplikuje na čísla 10 a 3 standardním způsobem.

flip

Ternární funkce, která si bere jako argumenty:

  • binární funkci f typu a -> b -> c
  • cokoli, co se dá použít jako druhý argument funkce f, typu b
  • cokoli, co se dá použít jako první argument funkce f, typu a

Následně prohodí pořadí druhého a třetího argumentu a tyto argumenty nechá zpracovat funkcí f, výsledek typu c.

Definice

flip       ::  (a -> b -> c) -> b -> a -> c
flip f x y  =  f y x

Příklad použití

flip (-) 3 5  ~>  5 - 3  ~>  2
flip const True "jj"  ~>  const "jj" True  ~>  "jj"

Konstruktor n-tic

  • Uspořádané dvojice se tvoří pomocí binárního operátoru (,).
  • Uspořádané trojice pak pomocí ternárního operátoru (,,).
  • Čtveřice pomocí operátoru (,,,) arity 4.
  • ...

Příklad použití

(,)  5     True        ~>  (5, True)
(,,) "aAa" 5.0  False  ~>  ("aAa", 5.0, False)

fst

Funkce, která z uspořádané dvojice vrátí její první složku.

Definice

fst      :: (a,b) -> a
fst (x,_) = x

Příklad použití

fst ("#&!",10.5) ~> "#&!"

snd

Funkce, která z uspořádané dvojice vrátí její druhou složku.

Definice

snd       ::  (a,b) -> b
snd (_,y)  =  y

Příklad použití

snd ("#&!",10.5)  ~>  10.5

Složené funkce


Krabičkové znázornění skládání funkcí

Ke skládání funkcí se používá ternární operátor (.). Složená funkce (f.g) ve výrazu (f.g) x nejdříve prožene argument x funkcí g a následně funkcí f.

Argumenty operátoru (.) jsou:

  • druhá funkce, která se má na argument aplikovat, typ (b -> c)
  • první funkce, která se má na argument aplikovat, typ (a -> b)
  • argument, na který se složená funkce aplikuje, typ a

Výsledkem výpočtu je argument x po aplikaci funkcí g a f v tomto pořadí. Typ c

Definice

(.)       ::  (b -> c) -> (a -> b) -> a -> c
(f . g) x  =  f (g x)

Příklad

Definujte binární funkci sndOdd, která z uspořádané dvojice čehokoli a celého čísla vybere její druhou složku a zjistí, zda je její hodnota lichá. Příklad požadovaného vyhodnocení:

sndOdd ("ahoj",5)  ~>*  True
sndOdd (True,8)    ~>*  False


Do funkce vhodím dvojici čehokoli a celého čísla a vypadne z ní Bool. Typ této funkce tedy bude následující:

sndOdd  ::  (a,Integer) -> Bool
Jednou z možností by bylo použít definici podle vzoru:
sndOdd (_,y)  =  odd y
My si zde ukážeme, jak tuto funkci definovat pomocí složené funkce. Chceme vytvořit funkci obecně znázorněnou modrou krabičkou na obrázku výše. Vhodíme do ní dvojici a vypadne z ní Bool.

Jako první si z uspořádané dvojice vytáhneme její druhou složku pomocí funkce snd:

snd (x,y)
Poté na výsledek aplikujeme funkci odd:
odd (snd (x,y))
Což můžeme napsat pomocí operátoru (.) jako složenou funkci. Výsledná definice bude tedy vypadat následovně:
sndOdd (x,y)  =  (odd.snd) (x,y)
Pokud se nám podaří dostat argument funkce úplně doprava, můžeme jej ze zápisu vynechat. Takovému zápisu se říká pointfree. O převodu definice funkce do pointfree tvaru se budeme podrobně bavit později. Prozatím nám bude stačit vědět, že následující zápis je zaměnitelný s předchozím:
sndOdd  =  odd.snd


Vyhodnocení výrazu (odd.snd) (True,8)