Ciele
- Naučiť sa definovať vlastné funkcie a používať ich.
- 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
- Simon Thompson: Haskell: the Craft of Functional Programming
- Harold Abelson, Gerald Jay Sussman: Structure and Interpretation of Computer Programs