Ciele
- Naučiť sa vytvárať vykonateľné programy.
- Oboznámiť sa s operáciami pre vstup a výstup.
- Oboznámiť sa s konceptom monád.
Postup
Krok 1: Spustiteľný program
Spustiteľný program v jazyku Haskell musí obsahovať funkciu main :: IO ()
.
Úloha 1.1
Vytvorte nový súbor hello.hs
, obsahujúci funkciu main
:
main :: IO ()
main = putStrLn "Hello world!"
Skompilujte tento program:
ghc hello.hs
Krok 2: Vstupné a výstupné akcie
Úloha 2.1
Upravte program na zobrazovanie histogramu tak, aby čítal zoznam čísel zo súboru, názov ktorého bude zadaný ako argument príkazového riadku.
Poznámka
Použite funkcie pre prácu so súbormi a funkciu getArgs. Potrebujete tiež pridať do kódu:
import System.Environment
Krok 3: Interakcia
Úloha 3.1
Vytvorte aplikáciu pre hádanie mysleného čísla: Nech počítač si myslí číslo a používateľ háda myslené číslo. Počítač nech po nesprávnom odhade povie, či je myslené číslo väčšie alebo menšie ako hádané.
Aby sme mohli používať doplňujúcu knižnicu random
, vytvoríme nový projekt. V novom adresári guess
spustíte príkaz pre vytvorenie projektu:
cabal init
Na všetky otázky stačí dať predvolenú odpoveď.
V súbore guess.cabal
pridajte závislosť na balík random
:
-- Other library packages from which modules are imported.
build-depends: base ^>=4.18.2.1,
random
Môžete použiť pomocnú funkciu randNumber na generovanie náhodného čísla na základe špecifikovaného intervalu a odovzdaného generátora:
module Main where
import System.Random
main :: IO ()
main = do
number <- randNumber 1 10
putStrLn ("Hello, " ++ show number ++ "!")
randNumber :: Int -> Int -> IO Int
randNumber a b = getStdGen >>= \gen -> return (fst (randomR (a, b) gen))
Teraz na spúšťanie programu vám stačí použiť príkaz:
cabal run
Krok 4: Monády
Typ IO
je len jedným z monadických typov. Haskell však definuje viacero takýchto typov. Pre všetky z nich je možné používať operátory >>=
, >>
na spájanie operácií a funkciu return
na zabalenie hodnoty do monády. Pritom to, čo sa vykoná pri spájaní operácii pomocou >>=
je definované typom. Pre IO
je to sekvenčné vykonávanie akcií, ale napríklad pre zoznam ([]
), ktorý je tiež monádou, je to vykonanie ďalšej operácie na každom elemente z výsledku predchádzajúcej operácie a spojenie výsledkov do jedného zoznamu (xs >>= f = concat (map f xs)
).
generation = replicate 3
test1 = ["bunny"] >>= generation
test2 = ["bunny"] >>= generation >>= generation
Ďalším príkladom monády je typ Maybe. V jeho prípade operátor >>=
prepája viacero operácií vracajúcich Maybe
tak, že ak niektorá z nich vráti Nothing
, potom celá reťaz vráti Nothing
. Majme, napríklad, funkciu getTaxOwed
, ktorá vyhľadá veľkosť dane naprieč niekoľkých databáz pomocou funkcie lookup (kompletný kód s databázami).
getTaxOwed :: String -> Maybe Double
getTaxOwed name =
case lookup name phonebook of
(Just number) -> case lookup number governmentDatabase of
(Just registration) -> lookup registration taxDatabase
Nothing -> Nothing
Nothing -> Nothing
Úloha 4.1
Zjednodušte funkciu getTaxOwed
s využitím monadického operátora >>=
.
Použitie operátora >>=
v prípade typov Maybe
a Either
umožňuje dosiahnuť efekt, podobný spracovávaniu výnimiek (exception handling). Prípadnú chybu nie je nutné ošetrovať v každom výraze kde môže vzniknúť, ale len na jednom mieste.