Kodutöö 6
Liidesed
Selles praktikumis tegeleme liidestega.
Konspekt
Lisalugemine (vabatahtlik ja kui 4. 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
Praktikumi ja kodutöö ülesanded
Kahendpuud
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] toList (Branch (Branch Leaf 3 Leaf) 5 (Branch Leaf 7 Leaf)) == [3, 5, 7]
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
Ratsionaalarvud
 NB! Tüübi Nat kasutamiseks lisa faili algusesse import Data.Nat.
Järgnevalt on defineeritud positiivsete ratsionaalarvude tüüp Rat ning näiteks ka ratsionaalarvude normaliseerimise funktsioon norm. Lisaks on skitseeritud mõned operatsioonid ratsionaalarvudel ning näitena väärtused pool ja neljandik.
infix 7 :/:
data Rat = (:/:) Nat Nat
-- normaliseerimine
norm : Rat -> Rat
norm (_   :/:   0) = 0 :/: 0
norm (0   :/:   _) = 0 :/: 1
norm (S a :/: S b) =
    let n = gcd (S a) (S b) in
    (S a) `div` n :/: (S b) `div` n
-- muud operatsioonid:
-- (a :/: b) == (c :/: d) = a*d == b*c
-- (a :/: b) +  (c :/: d) = a*d + b*c :/: b*d
-- (a :/: b) *  (c :/: d) = a*c :/: b*d 
-- (a :/: b) /  (c :/: d) = a*d :/: b*c 
-- pöörd (a :/: b) = b :/: a
neljandik : Rat
neljandik = 1 :/: 4
pool : Rat
pool = 1 :/: 2
4. Eq liides
Defineerige Eq liides ratsionaalarvudele.
1 :/: 2 == pool 2 :/: 4 == pool
5. Num liides
Defineerige Num liides ratsionaalarvudele.
pool + pool == 1 2 * pool == 1 pool * pool == neljandik
6. Fractional liides
Defineerige Fractional liides ratsionaalarvudele.
pool / pool == 1 2 / pool == 4 recip pool == 2
recip on lühend sõnast reciprocal, inglise keeles pöördväärtus.
7. Ord liides ratsionaalarvudele
Defineerige Ord liides ratsionaalarvudele.
compare (1:/:2) (1:/:3) == GT compare (1:/:4) (1:/:3) == LT compare (3:/:3) (2:/:2) == EQ
8. Monus liides
Naturaalarvudel ei saa defineerida tavalist lahutamist aga saab defineerida monus operaatori.
infixl 8 -. interface Monus t where (-.) : t -> t -> t
Esmalt, defineerige Monus liides arvudele millel on minus ja pöördväärtus (Neg).
Neg a => Monus a where x -. y = ?rhs_monus_neg
0.5 -. 0.3 == 0.2 5 -. 3 == 2 3 -. 5 == -2
9. Monus liides naturaalarvudele
Nüüd, defineerige Monus liides naturaalarvudele.
S (S Z) -. S Z == S Z S (S Z) -. S (S Z) == Z S (S Z) -. S (S (S Z)) == Z
10. Monus liides ratsionaalarvudele
Nüüd, defineerige Monus liides ratsionaalarvudele.
(1 :/: 3) -. (1 :/: 6) == (1 :/: 6) (1 :/: 6) -. (1 :/: 3) == (0 :/: 1) (1 :/: 2) -. (1 :/: 3) == (1 :/: 6)
11. Range liides ratsionaalarvudele
Nüüd, defineerige Range liides ratsionaalarvudele.
[1:/:1 .. 5] == [(1 :/: 1), (2 :/: 1), (3 :/: 1), (4 :/: 1), (5 :/: 1)] [1:/:2 .. 5:/:1] == [(1 :/: 2), (3 :/: 2), (5 :/: 2), (7 :/: 2), (9 :/: 2)] [0, 1:/:2 .. 2] == [(0 :/: 1), (1 :/: 2), (1 :/: 1), (3 :/: 2), (2 :/: 1)] [0, 1:/:8 .. 1] == [(0 :/: 1), (1 :/: 8), (1 :/: 4), (3 :/: 8), (1 :/: 2), (5 :/: 8), (3 :/: 4), (7 :/: 8), (1 :/: 1)] take 5 [0:/:1..] == [(0 :/: 1), (1 :/: 1), (2 :/: 1), (3 :/: 1), (4 :/: 1)] take 5 [0:/:1, 1:/:3 ..] == [(0 :/: 1), (1 :/: 3), (2 :/: 3), (1 :/: 1), (4 :/: 3)]
Lisaülesanded
(Valikuliselt tehtavad ülesanded, mis on sarnase keerukusega kui kodutöö ülesanded.)
12. Range instantsi üldistamine
Üldistage Range Rat instansi, et see ei töötaks vaid ratsionaalarvude korral, vaid tingimusel et see rahuldab mingit konkreetset nimekirja liideseid. Mis liideseid oleks tarvis?
Näiteks: (samad testid mis eelmise ülesande juures)
Tärnülesanded
(Valikuliselt tehtavad ülesanded, mis on keerulisemad/raskemad kui kodutöö ülesanded.)
13*. Traversable liides
Tahame arvutada kõik variandid puudest, kus puu olevatest väärtustest võidakse võtta vastandarv.
Kui puude asemel võtta listid, saame seda lahendada traverse funktsiooniga nii:
variandidList : List Int -> List (List Int) variandidList = traverse (\ x => [x,-x])
Et selline kood töötaks puude puhul, tuleb esmalt implementeerida Traversable liides.
Traversable Tree where traverse g t = ?tree_trav variandidTree : Tree Int -> List (Tree Int) variandidTree = traverse (\ x => [x,-x])
Testkood
variandidTree (Branch (Branch Leaf 1 Leaf) 2 (Branch Leaf 3 Leaf)) == [Branch (Branch Leaf 1 Leaf) 2 (Branch Leaf 3 Leaf), Branch (Branch Leaf 1 Leaf) 2 (Branch Leaf -3 Leaf), Branch (Branch Leaf 1 Leaf) -2 (Branch Leaf 3 Leaf), Branch (Branch Leaf 1 Leaf) -2 (Branch Leaf -3 Leaf), Branch (Branch Leaf -1 Leaf) 2 (Branch Leaf 3 Leaf), Branch (Branch Leaf -1 Leaf) 2 (Branch Leaf -3 Leaf), Branch (Branch Leaf -1 Leaf) -2 (Branch Leaf 3 Leaf), Branch (Branch Leaf -1 Leaf) -2 (Branch Leaf -3 Leaf)]
Vihjeks, traverse on map-i abstraktne vorm, kus on lisatud pure ja <*>-id.  Listide Functor ja Traversable on implementeeritud nii:
Functor List where --map : (a -> b) -> List a -> List b map f [] = [] map f ((::) x xs) = (::) (f x) (map f xs) Traversable List where --traverse : Applicative h => (a -> h b) -> List a -> h (List b) traverse f [] = pure [] traverse f (x::xs) = pure (::) <*> (f x) <*> (traverse f xs)
Funktsiooni traverse kasutatakse tihti sisendi-väljundiga. Proovi REPL-ist käivitada 
:exec traverse printLn [1,2,3]