5. Praktikum
Selles praktikumis tegeleme liidestega ning õpime kasutama sisend-väljund ja Maybe monaade.
Liidesed
Lisalugemine (vabatahtlik ja kui eelmises praktikumis juba ei lugenud):
Type-Driven development with Idris peatükid:
- Chapter 7. Interfaces: using constrained generic types, sissejuhatus ja alampeatükid:
- 7.1. Generic comparisons with Eq and Ord
- 7.1.1. Testing for equality with Eq
- 7.1.2. Defining the Eq constraint using interfaces and implementations
- 7.1.3. Default method definitions
- 7.1.4. Constrained implementations
- 7.1.5. Constrained interfaces: defining orderings with Ord
- 7.1. Generic comparisons with Eq and Ord
1. map
-i liides
Kirjuta Functor
liidese instants Tree
tüübile.
data Tree a = Leaf | Branch (Tree a) a (Tree a) Eq a => Eq (Tree a) where Leaf == Leaf = True (Branch x y z) == (Branch w v s) = x==w && y==v && z==s _ == _ = False Functor Tree where map f t = ?rhs_map
Näiteks:
map (+10) (Branch Leaf 5 Leaf) == (Branch Leaf 15 Leaf) map (+10) (Branch (Branch Leaf 4 Leaf) 3 (Branch Leaf 5 Leaf)) == (Branch (Branch Leaf 14 Leaf) 13 (Branch Leaf 15 Leaf))
2. fold
-i liides
Kirjuta Foldable
liidese instants Tree
tüübile foldr
kaudu. Pane tähele, et tegemist pole Tree
andmestruktuuri "loomuliku" foldiga, vaid listi-foldr
-ga.
Foldable Tree where foldr f b t = ?rhs_foldr
Veendu, et nüüd saab meie puudel muuhulgas kasutada toList
funktsiooni, mis peaks käituma nagu eelmise praktikumi tree2list
.
Näiteks:
toList Leaf == [] toList (Branch Leaf 5 Leaf) == [5]
3. Üldine pikkus
Kirjuta len
funktsioon, millega saab arvutada nii listi pikkust kui ka puu suurust.
len : Foldable t => t a -> Int
Näiteks:
len [1,2,3] == 3 len (Branch Leaf 5 Leaf) == 1
Do-notatsioon ja Sisend-väljund
Lisalugemine (vabatahtlik):
Type-Driven development with Idris peatükid:
- Chapter 1. Overview, alampeatükk:
- 1.3.2. Side-effecting programs
- Chapter 5. Interactive programs: input and output processing, sissejuhatus ja alampeatükid:
- 5.1. Interactive programming with IO
- 5.1.1. Evaluating and executing interactive programs
- 5.1.2. Actions and sequencing: the >>= operator
- 5.1.3. Syntactic sugar for sequencing with do notation
- 5.2. Interactive programs and control flow
- 5.2.1. Producing pure values in interactive definitions
- 5.1. Interactive programming with IO
4. Funktsioon dialoog
Kirjuta protseduur dialoog
, mis küsib kasutajalt nime ja tervitab teda sellega.
dialoog : IO () dialoog = ?rhs_dialoog
5. Listi trükk
Kirjuta funktsioon, mis prindib talle argumendina antud arvude listi. Iga prinditav arv peab tulema eraldi reale. Näiteks:
> prindiArvud [1,66,99] 1 66 99
prindiArvud : List Int -> IO () prindiArvud xs = ?rhs_prindiArvud
6. Arvude sisetamine
Kirjuta protseduur, mis esmalt küsib kasutajalt arvu. Kui kasutaja sisestab mittearvu, tuleb veast teatada ning uuesti arvu küsida. Protseduur tagastab edukalt sisestatud arvu.
readMaybe : IO (Maybe Int) readMaybe = do input <- getLine if all isDigit (unpack input) then pure (Just (cast input)) else pure Nothing loeArv : IO Int loeArv = ?rhs_loeArv
7. Kahe arvu summa
Kirjuta protseduur, mis küsib kasutajalt kaks arvu ning trükib nende summa.
summa2 : IO () summa2 = ?rhs_summa2
8. Arvude summa
Kirjuta protseduur, mis esmalt küsib arvu n, seejärel loeb n arvu ning lõpuks trükib viimati loetud n arvu summa. Proovige lahendada seda lihtrekursiooniga kui ka kasutades näiteks sequence
funktsiooni.
Lihtsustatult, võtab sequence : List (IO a) -> IO (List a)
listi arvutusi ja teeb need järjest ning tagastab listi tulemustega. Sarnaselt töötab ka traverse : (a -> IO b) -> List a -> IO (List b)
.
summaN1 : IO () summaN1 = ?rhs_summaN1 summaN2 : IO () summaN2 = ?rhs_summaN2
9. Arvu arvamise mäng
Implementeeri klassikaline mäng, mis valib juhusliku arvu nullist sajani ning kasutaja peab selle ära arvama. Kasutaja saab pakkuda arve ja programm ütleb, kas pakutud arv on suurem, võrdne või väiksem. Kui vastus on võrdne (s.t. pakutud arv on võrdne juhuslikult valitud arvuga) on mäng läbi ja trükitakse pakkumiste arv.
> :exec m2ng Arva ära täisarv vahemikus nullist sajani! Sisesta number: 50 Ei! Minu number on suurem Sisesta number: 62 Ei! Minu number on väiksem Sisesta number: 61 Ära arvasid! Oligi 61. Pakkusid 3 korda.
m2ng : IO () m2ng = ?rhs_m2ng
10. Maybe
monaad
Olgu antud järgmine avaldispuude andmestruktuur:
data Expr = Const Int | Add Expr Expr | Div Expr Expr expr1 : Expr expr1 = Div (Add (Const 3) (Const 1)) (Const 2) expr2 : Expr expr2 = Add (Const 1) (Div (Const 1) (Add (Const 1) (Const (-1))))
Kasutada do
-notatsiooni, kirjuta funktsioon, mis väärtustab avaldispuu või tagastab Nothing
kui selles tekib nulliga jagamine:
evalExpr : Expr -> Maybe Int evalExpr e = ?rhs_evalExpr
Näiteks:
evalExpr expr1 == Just 2 evalExpr expr2 == Nothing
Tärnülesanded
m2ngR
Implementeeri arvu äraarvamise mängu pöördversioon, kus kasutaja valib mõttes (juhusliku) arvu ja programm püüab seda ära arvata. Programm peaks ära tundma sohitegemise, kui kasutaja on vastanud enesele vasturääkivalt.
m2ngR : IO () m2ngR = ?rhs_m2ngR