3.2. Polymorfní typy

Haskell také obsahuje polymorfní typy - typy, které jsou nějakým způsobem univerzálně kvantifikované přes všechny typy. Polymorfní typové výrazy popisují v podstatě rodiny typů. Například (pro všechna a) [a] je rodina typů tvořená pro každý typ a typem seznam hodnot typu a. Seznamy celých čísel (např. [1,2,3]), seznamy znaků  (['a','b','c']), nebo dokonce seznamy seznamů celých čísel atd. jsou všechno prvky této rodiny. (Všimněte si ale, že  [2,'b'] není platný příklad, neboť neexistuje žádný typ obsahující jak 2, tak i 'b'.)


Poznámka:
Poznámka:
Identifikátory jako výše uvedené a se nazývají typové proměnné a zapisují se s malým počátečním písmenem, abychom je odlišili od specifických typů jako Int. A dále vzhledem k tomu, že Haskell má pouze univerzálně kvantifikované typy, není třeba explicitně vypisovat symbol pro univerzální kvantifikátor a v uvedeném příkladu tedy píšeme jednoduše jen [a]. Jinými slovy, všechny typové proměnné jsou implicitně univerzálně kvantifikované.

Seznamy jsou ve funkcionálních jazycích běžně používané datové struktury a jsou dobrým prostředkem pro vysvětlení principů polymorfismu. Seznam [1,2,3] je v Haskellu vlastně zkratkou pro seznam 1:(2:(3:[])), kde [] je prázdný seznam a  : je infixový operátor, jenž přidá svůj první argument na začátek svého druhého argumentu (seznamu).  (: a [] jsou obdobou cons a nil jazyka LISP.) Vzhledem k tomu, že : je zprava asociativní, můžeme tento seznam psát také ve tvaru 1:2:3:[].

Jako příklad uživatelem definované funkce, která pracuje nad seznamem, uvažujme problém určení počtu prvků v seznamu:

length :: [a] -> Int
length [] = 0
length (x:xs) = 1 + length xs
Tato definice je téměř samovysvětlující. Rovnice můžeme číst takto: „Délka prázdného seznamu je 0 a délka seznamu, jehož prvním prvkem je x a zbytek xs, je 1 plus délka xs.“


Poznámka:
Poznámka:
Povšimněte si použitých konvencí pro pojmenování, xs je v angličtině množným číslem od x a mělo by se to takto i chápat.

Ačkoliv je tento příklad intuitivní, zdůrazňuje důležitý aspekt jazyka Haskell, jenž je třeba ještě vysvětlit: unifikace vzorů. Levá strana rovnic obsahuje vzory jako [] a x:xs. Při aplikaci funkce jsou tyto vzory docela intuitivním způsobem unifikovány se skutečnými parametry ([] odpovídá pouze prázdnému seznamu a x:xs se úspěšně unifikuje s libovolným alespoň jednoprvkovým seznamem, přičemž se x naváže na první prvek a xs na zbytek seznamu). Pokud se unifikace podaří, vyhodnotí se pravá strana a její hodnota se vrátí jako výsledek aplikace. Pokud unifikace neuspěje, vyzkouší se další rovnice a pokud žádná rovnice neuspěje, vznikne chyba.

Definování funkce pomocí unifikace vzorů je v jazyce Haskell celkem běžné a uživatel by se měl s různými povolenými tvary vzorů seznámit. K tomuto problému se vrátíme ještě později.

Funkce length je rovněž příkladem polymorfní funkce. Lze ji aplikovat na seznam obsahující prvky libovolného typu, například [Int], [Char] nebo [[Int]].

length [1,2,3] => 3
length ['a','b','c'] => 3
length [[1],[2],[3]] => 3

Dále zde máme dvě další polymorfní funkce nad seznamy, které později použijeme. Funkce head vrací první prvek seznamu, funkce tail vrací všechno kromě prvního prvku.

head :: [a] -> a
head (x:xs) = x

tail :: [a] -> [a]
tail (x:xs) = xs
Na rozdíl od length tyto funkce nejsou definovány pro všechny možné hodnoty argumentu. Jsou-li tyto funkce aplikovány na prázdný seznam, vznikne při výpočtu chyba.

S polymorfními typy zjišťujeme, že některé typy jsou v jistém smyslu obecnější než jiné tím, že množina hodnot. kterou definují, je větší. Například typ [a] je obecnější než [Char]. Jinými slovy, druhý typ lze odvodit z prvního vhodnou substitucí za a. S ohledem na toto uspořádání podle obecnosti má typový systém jazyka Haskell dvě důležité vlastnosti: pro každý správně typovaný výraz je garantována existence jediného hlavního typu (vysvětlíme dále) a tento hlavní typ lze odvodit automaticky. V porovnání s monomorfně typovaným jazykem jako je C dojdeme k tomu, že polymorfismus zlepšuje vyjadřovací schopnosti jazyka a že typová inference snižuje zátěž programátora způsobenou existencí typů.

Hlavní typ výrazu nebo funkce je nejméně obecný typ, jenž intuitivně „zahrnuje všechny instance výrazu.“ Například hlavním typem funkce head je [a]->a; typy [b]->a, a->b nebo dokonce a jsou příliš obecné, zatímco něco jako [Int]->Int je zase příliš specifické. Existence unikátních hlavních typů je nejslavnější vlastností Hindley-Milnerova typového systému, jenž tvoří základ typového systému jazyků Haskell, ML, Miranda („Miranda“ je obchodní značkou Research Software, Ltd.) a několika dalších (většinou funkcionálních) jazyků.