Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.
| Obě strany předchozí revizePředchozí verzeNásledující verze | Předchozí verze | ||
| msz:haskell_lazy [29. 05. 2012, 10.07:25] – [Líné vyhodnocení] wiki pitel | msz:haskell_lazy [03. 08. 2026, 08.31:25] (aktuální) – odstraněno - upraveno mimo DokuWiki (Neznámé datum) 127.0.0.1 | ||
|---|---|---|---|
| Řádek 1: | Řádek 1: | ||
| - | ====== Haskell – lazy evaluation ====== | ||
| - | [[wp> | ||
| - | Funkcionální jazyk, který je case-sensitive. Ke všemu má ještě speciální pravidla pro první znaky literálů. Je nutné dodržovat při psaní programu tato pravidla: | ||
| - | * Jména typů, typových tříd a datové konstruktory musejí mít velké počáteční písmeno | ||
| - | * Ostatní literály musejí mít písmeno malé | ||
| - | |||
| - | ===== Datové typy ===== | ||
| - | * Primitivní typy | ||
| - | * **'' | ||
| - | * **'' | ||
| - | * **'' | ||
| - | * **'' | ||
| - | * Strukturované typy | ||
| - | * **// | ||
| - | * **// | ||
| - | |||
| - | Haskell je silně typovaný jazyk. Změna jednoho typu na druhý je možná pouze zavoláním převodní funkce a každá entita má přesně daný svůj typ. Pro popis typu vstupu a výstupu funkce se používá zápis (příklad konstruktoru seznamu): | ||
| - | <code haskell> | ||
| - | Tento zápis říká asi toto: Funkce se jménem '' | ||
| - | Jelikož se jedná o jazyk silně typovaný, tak aby pro každý vstup nemuselo existovat několik definicí stejného operátoru, tak se zavádějí **typové proměnné**. Ty nahrazují skutečné typy a při vyhodnocení jsou nahrazeny skutečnými typy. Zápis vypadá následovně: | ||
| - | <code haskell> | ||
| - | Za symbol **'' | ||
| - | |||
| - | ===== Funkce ===== | ||
| - | Funkce **'' | ||
| - | |||
| - | Funkce součtu dvou prvků a druhé mocniny vypadá následovně: | ||
| - | <code haskell> | ||
| - | square x = x * x</ | ||
| - | Práci se seznamem jako parametrem ukazuje funkce, která počítá délku seznamu: | ||
| - | <code haskell> | ||
| - | length (x:xs) = 1 + length xs</ | ||
| - | Vyhodnocení funkcí probíhá od shora dolů, proto funkce, které popisují nadmnožinu ostatních případů, musejí být uvedeny jako poslední. První funkce se ztotožní s prázdným seznamem a vrací nulu. Když ne vstupu není prázdný seznam, tak se přistoupí ke druhé funkci. Tam se vzor chápe jako seznam, který má na začátku prvek zastoupený parametrem **'' | ||
| - | |||
| - | ==== Pojmenování části vzoru ==== | ||
| - | Při spojování dvou seznamů nás nezajímá pouze hlavička a zbytek seznamu. Je potřeba pracovat s jedním parametrem jako celkem, proto si ho můžeme pojmenovat(viz jména **'' | ||
| - | <code haskell> | ||
| - | merge l1 [] = l1 | ||
| - | merge l1@(x:xs) l2@(y:ys) = | ||
| - | if x<y then x:merge xs l2 else y:merge l1 ys</ | ||
| - | |||
| - | ==== Anonymní proměnné ==== | ||
| - | Funkce vrací hlavičku seznamu. Zbytek nás nezajímá, proto je pouze naznačeno, že by tam mělo něco být, ale nemá to konkrétní název. | ||
| - | <code haskell> | ||
| - | |||
| - | ==== Lokální funkce ==== | ||
| - | Jsou definované za klíčovým slovem **'' | ||
| - | <code haskell> | ||
| - | sqr a b = a * b | ||
| - | xx = sqr x x | ||
| - | yy = sqr y y</ | ||
| - | Jinou možností zápisu lokálních funkcí je využití konstrukce ''' | ||
| - | <code haskell> | ||
| - | let | ||
| - | sqr a b = a * b | ||
| - | xx = sqr x x | ||
| - | yy = sqr y y | ||
| - | in | ||
| - | xx + yy</ | ||
| - | |||
| - | ===== Líné vyhodnocení ===== | ||
| - | [[wp> | ||
| - | |||
| - | Tato strategie vyhodnocení uvádí do absolutní perfekce strategii vyhodnocení označovanou, | ||
| - | |||
| - | Příkladem, | ||
| - | <code haskell> | ||
| - | Pokud by nebyl Haskell jazyk s líným vyhodnocením, | ||
| - | <code haskell> | ||
| - | take 10 [-1, -3..] == [-1, -3, -5, -7, -9, -11, -13, -15, -17, -19]</ | ||
| - | Výsledek líného vyhodnocení může být použit přes výpočtovou sekvenci celé funkce. | ||
| - | ===== Rekurze ===== | ||
| - | * **Zpětná rekurze** – Pokud po návratu z rekurzivního volání probíhá ještě nějaký výpočet. // | ||
| - | * **Dopředná rekurze** – Pokud rekurzivní volání je poslední část výpočtu. // | ||
| - | * **Lineární rekurze** – Ve výpočtu rekurze je právě jedno rekurzivní volání funkce. Tento typ rekurze lze převést na cyklus. | ||
| - | * **Koncová rekurze** – Dopředně lineární rekurze. Každou takovouto funkci lze převést na efektivní cyklus! Není potřeba uchovávat stav nedokončených výpočtů. | ||