5.2. Generátory seznamů

Často potřebujeme vyjádřit seznam pomocí toho, jaké vlastnosti mají mít jeho prvky. Tuto notaci vlastně už znáte z matematiky, kde se setkáváme s notací pro „množinu takových prvků x, které jsou z množiny A a platí pro ně podmínka p“, neboli { x | x in A, p x }.

Podstatou notace, kterou budeme dále nazývat generátor seznamu, je to, že vytváříme popis seznamu pomocí prvků jiného seznamu. Z tohoto zdrojového seznamu postupně bereme jednotlivé prvky, testujeme je a transformujeme na prvky cílového seznamu. Pomocí generátorů seznamu jsme schopni jednoduše a kompaktně zapsat spoustu užitečných výpočtů, které se nám budou hodit. Nejlépe si vše ukážeme na příkladech.

Příklad 5.1.
Nechť seznam xs = [2,5,1], potom generátor [2*x | x <- xs] představuje seznam [4, 10, 2], tj. obsahuje všechny prvky původního seznamu vynásobené dvěma. Tento zápis můžeme číst přímo jako „Vezmi všechna 2*x, kde x patří do xs“.
Příklad 5.2.
Pro konstrukci seznamu můžeme případně použít pouze ty prvky zdrojového seznamu, které splňují nějakou dodatečnou podmínku. Například
         [ 2*x | x <- xs, isEven x, x > 3 ]  
představuje seznam tvořený hodnotami 2*x, přičemž x je ze seznamu xs, je sudé a větší než 3, tedy výsledek je sezam [10], pokud uvažujeme stejný zdrojový seznam xs jako v předchozím příkladu.

Cvičení
Cvičení
Definujte funkci
        divisors :: Int -> [Int]
která vrátí seznam všech dělitelů zadaného kladného čísla. Pomocí této funkce pak definujte predikát
        isPrime :: Int -> Bool
jenž otestuje, zda je zadané číslo prvočíslem.