Úvod do jazyka Haskell

Ciele

  1. Naučiť sa definovať vlastné funkcie a používať ich.
  2. Zopakovať si rekurziu a naučiť sa definovať rekurzívne funkcie.

Postup

Krok 1: Jednoduché funkcie

Funkcie v jazyku Haskell sa píšu v súbore s príponou .hs. Definícia funkcie má tvar názovFunkcie parametre = výraz, napríklad:

add x y = x + y

Haskell je kompilovaný jazyk, ale existuje aj interaktívny interpretátor GHCi, ktorý umožňuje rýchlo skúšať zabudované aj vlastné funkcie. Po spustení GHCi je možné zadávať výrazy a sledovať ich výsledky.

Úloha 1.1

Vytvorte si súbor cvicenie.hs a zapíšte doň definíciu funkcie add. Načítajte tento súbor do interaktívneho interpretátora pomocou príkazu :load cesta/k/súboru.hs alebo jeho spustením s názvom súboru ako parametrom:

ghci cvicenie.hs

Skúste použiť funkciu add v interpretátore.

Úloha 1.2

Definujte funkciu hypotenuse, ktorá vypočíta dĺžku prepony pravouhlého trojuholníka na základe dĺžok odvesien. Použite pritom funkciu sqrt na výpočet odmocniny.

Poznámka

Po zmene súboru je možné ho znovu načítať pomocou príkazu :r alebo :reload.

Poznámka

Na výpočet druhej mocniny čísla môžete použiť operátor ^.

Podmienené vykonávanie je možné dosiahnuť pomocou tzv. strážcov (guards):

factorial n
    | n == 1 = 1
    | n >= 1 = n * factorial (n-1)

Poznámka

Telo funkcie musí byť odsadené keďže Haskell, podobne ako Python, používa odsadzovanie ako časť syntaxe.

Úloha 1.3

Definujte funkciu middleNumber, ktorá vráti stredné z troch zadaných čísel:

middleNumber :: Integer -> Integer -> Integer -> Integer

Príklady použitia:

middleNumber 5 3 8 == 5
middleNumber 1 1 1 == 1

Úloha 1.4

Definujte funkciu average pre výpočet celočíselného aritmetického priemeru zoznamu čísel. Použite pritom funkcie sum (súčet čísel), length (dĺžka zoznamu) a div pre celočíselné delenie.

listAverage :: [Int] -> Int

Krok 2: Rekurzia

Jedným zo spôsobov ako riešiť komplexnejšie úlohy, ktoré vyžadujú opakovanie nejakej operácie viackrát, je rekurzia.

Úloha 2.1

Definujte funkciu sumDigits, ktorá spočíta súčet číslic v zadanom celom čísle.

sumDigits :: Int -> Int

Príklad použitia:

sumDigits 123 == 6

Poznámka

Na získanie poslednej číslice čísla môžete použiť operáciu mod (zvyšok po delení), na odstránenie poslednej číslice môžete použiť celočíselné delenie div.

Úloha 2.2

Definujte funkciu isPalidrome, ktorá určí, či zadané číslo je palindróm:

isPalindrome :: Int -> Bool
isPalindrome n = n == reverseNumber n
  where
    reverseNumber ...

Príklady použitia:

isPalindrome 12345 == False
isPalindrome 1234321 == True

Krok 3: Newtonová metóda

Na približný výpočet odmocniny je možné použiť Newtonovú metódu. Jej podstata spočíva v postupnom spresňovaní aproximácie. Ak y je odhad hodnoty druhej odmocniny čísla x, tak lepší odhad dokážeme vypočítať ako priemer čísel y a x/y.

Takže v každom kroku výpočtu je možné overiť, či odhad je už dostatočne presný, a ak nie je, vypočítať presnejší. Na overenie nám stačí vypočítať mocninu odhadu y a porovnať ju s odmocňovaným číslom x. Ich rozdiel musí byť menší ako nejaká stanovená hranica, napríklad:

$$ \left| y^2 - x \right| < 0,001 $$

Úloha 3.1

Definujte funkciu newtonSqrt pre výpočet druhej odmocniny pomocou Newtonovej metódy. Definujte si tiež pomocné funkcie

  • sqrtIter pre rekurzívne spresňovanie aproximácie,
  • improve pre výpočet lepšej aproximácie,
  • goodEnough pre jej overenie.

Poznámka

Na výpočet absolútnej hodnoty čísla môžete použiť štandardnú funkciu abs.

Zdroje