Výrazy a funkcie

Ciele

  1. Naučiť sa používať interaktívny interpretátor GHCi.
  2. Naučiť sa definovať vlastné funkcie a používať ich.
  3. Zopakovať si rekurziu a naučiť sa definovať rekurzívne funkcie.

Postup

Krok 1: Definícia funkcií a ich aplikácia v interaktívnom interpretátore

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.

Krok 2: Jednoduché funkcie

Úloha 2.1

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 a operátor ^ na výpočet druhej mocniny.

Poznámka

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

Úloha 2.2

Definujte funkciu isLeapYear, ktorá určí, či zadaný rok je priestupný. Rok je priestupný, ak je deliteľný 4 ale zároveň nie je deliteľný 100, alebo ak je deliteľný 400. Použite bežné logické operátory a funkciu mod na zistenie deliteľnosti.

Typ funkcie isLeapYear by mohol byť:

isLeapYear :: Int -> Bool

Poznámka

Funkcie dvoch argumentov je možné používať aj ako operátory ak sa ich názov uzavrie do spätných apostrofov. Napríklad, tieto dva výrazy sú ekvivalentné:

mod 10 3
10 `mod` 3

Úloha 2.3

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 3: Podmienené vykonávanie

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 3.1

Definujte funkciu grade, ktorá na základe počtu bodov získaného z predmetu vráti písmenkovú známku (A, B, C, D, E, FX). V prípade neplatného vstupu, nech je výsledkom reťazec "Invalid score".

grade :: Int -> String

Úloha 3.2

Definujte funkciu ticketPrice age, ktorá na základe veku osoby vráti cenu vstupenky do kina. Štandardná cena je 8 eur, pre deti do 15 rokov a seniorov nad 65 rokov je zľava 50%.

ticketPrice :: Int -> Double

Krok 4: Rekurzia

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

Úloha 4.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 (modulo, zvyšok po delení), na odstránenie poslednej číslice môžete použiť celočíselné delenie div.

Úloha 4.2

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

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

reverseNumber n = ...

Príklady použitia:

isPalindrome 12345 == False
isPalindrome 1234321 == True

Poznámka

Definujte ďalšie pomocné funkcie podľa potreby.

Krok 5: 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 5.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