5. Haskelli praktikum
Selles praktikumis harjutame andmestruktuuride ja tüübiklasside kasutamist.
Näiteülesanded
E-maili andmestruktuur
data Email = E String String kalmer, varmo, simmo :: Email kalmer = E "kalmer.apinis" "ut.ee" varmo = E "varmo.vene" "ut.ee" simmo = E "simmo.saan" "ut.ee"
Implementeerige show
operaator e-maili andmestruktuuri jaoks nii,
et ülaldefineeritud aadressid näidataks standardsel kujul:
show kalmer == "kalmer.apinis@ut.ee"
Kirja (kirje) andmestruktuur
data Kiri = K { saatja :: Email, saajad :: [Email], pealkiri :: String, sisu :: String } deriving (Show)
Kirjutage Kiri
tüüpi väärtus, mis tähistaks kirja teilt arvutiteaduse instituudi juhatajale.
testkiri :: Kiri testkiri = undefined
Kirjuta funktsioon pealkiriSisu :: Kiri -> String
, mis tagastab kirja kujul pealkiri: sisu
.
Puu andmestruktuur
data Tree a = Leaf | Branch (Tree a) a (Tree a) deriving (Show)
Defineerige puu kõrguse funktsioon height :: Tree a -> Int
ja puude võrdsuskontroll (==)
.
Harjutusülesanded
Ülesanne 1
Defineerige Tree a
andmetüübi jaoks elementide arvu funktsioon size
.
size :: Tree a -> Int size = undefined
Ülesanne 2
Defineerige Tree a
andmetüübi jaoks sisalduvusoperaator memberOf
.
memberOf :: Eq a => a -> Tree a -> Bool memberOf = undefined
Ülesanne 3
Defineerige predikaat balanced :: Tree a -> Bool
, mis kontrollib et harude kõrgused ei erineks rohkem kui ühe võrra.
balanced Leaf == True balanced (Branch (Branch Leaf 'x' Leaf) 'x' (Branch Leaf 'x' Leaf)) == True balanced (Branch (Branch Leaf 'x' Leaf) 'x' Leaf) == True balanced (Branch Leaf 'x' (Branch Leaf 'x' Leaf)) == True balanced (Branch (Branch (Branch Leaf 'x' Leaf) 'x' Leaf) 'x' Leaf) == False balanced (Branch (Branch (Branch (Branch Leaf 'x' Leaf) 'x' Leaf) 'x' Leaf) 'x' (Branch (Branch (Branch Leaf 'x' Leaf) 'x' Leaf) 'x' Leaf)) == False
balanced :: Tree a -> Bool balanced = undefined
Ülesanne 4
Defineerige funktsioon gen
mis tagastab mittenegatiivse täisarvu jaoks täpselt sellise kõrgusega täieliku kahendpuu. Näiteks:
gen 0 'x' == Leaf gen 1 'x' == Branch Leaf 'x' Leaf gen 2 'x' == Branch (Branch Leaf 'x' Leaf) 'x' (Branch Leaf 'x' Leaf) . . .
gen :: Int -> a -> Tree a gen = undefined
Ülesanne 5
Defineerige funktsioon tree2list
mis teisendab puu listiks keskjärjestuses. Näiteks:
tree2list Leaf == [] tree2list (Branch Leaf 1 Leaf) == [1] tree2list (Branch (Branch Leaf 1 Leaf) 2 (Branch Leaf 3 Leaf)) == [1,2,3] . . .
tree2list :: Tree a -> [a] tree2list = undefined
Ülesanne 6
Defineerige funktsioon list2tree
, mis teisendab listi puuks. Näiteks:
list2tree [] == Leaf list2tree [1] == (Branch Leaf 1 Leaf) list2tree [1,2,3] == (Branch (Branch Leaf 1 Leaf) 2 (Branch Leaf 3 Leaf))
list2tree :: [a] -> Tree a list2tree = undefined
Püüdke lahendada ülesanne nii,et tagastatud puu oleks balanseeritud.
Ülesanne 7
Kirjuta Functor
tüübiklassi instants Tree
tüübile.
instance Functor Tree where fmap f t = undefined
Ülesanne 8
Kirjuta Foldable
tüübiklassi instants Tree
tüübile foldr
kaudu. Võid proovida seda teha ka foldMap
kaudu.
instance Foldable Tree where foldr f b t = undefined -- või -- foldMap f t = undefined
Veendu, et nüüd saab meie puudel muuhulgas kasutada standardseid length
, elem
ja toList
(impordi Data.Foldable
) funktsioone, mis peaks käituma nagu ülaldefineeritud size
, memberOf
ja tree2list
.
Ülesanded*
2×2 maatriksi andmestruktuur
data Mat22 a = Mat22 a a a a deriving (Show, Eq)
Näiteks Mat22 1 2 3 4
esitab 2×2 maatriksit {$ \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} $}.
Ülesanne 9
Kirjuta Semigroup
ja Monoid
tüübiklasside instantsid Mat22
tüübile nii, et (<>)
operaator korrutaks maatriksid ja mempty
oleks ühikmaatriks. 2×2 maatriksite korrutis avaldub järgnevalt:
{$ \begin{pmatrix} a & b \\ c & d \end{pmatrix} \begin{pmatrix} e & f \\ g & h \end{pmatrix} = \begin{pmatrix} ae+bg & af+bh \\ ce+dg & cf+dh \end{pmatrix} $}
instance Num a => Semigroup (Mat22 a) where (Mat22 a b c d) <> (Mat22 e f g h) = undefined stimes = stimesMonoid -- fibMonoid jaoks vajalik definitsioon instance Num a => Monoid (Mat22 a) where mempty = undefined
Korrektse lahenduse korral arvutab järgnevalt antud funktsioon n-inda Fibonacci arvu efektiivselt keerukusega {$ \mathcal{O}(\log n) $}, kasutades äsjadefineeritud maatriksite korrutamise monoidi:
fibMonoid :: (Integral a, Num b) => a -> b fibMonoid n = fn where Mat22 _ fn _ _ = stimes n (Mat22 1 1 1 0)
Selle matemaatilist tausta võib lugeda näiteks Wikipediast.
Ülesanne 10
Kirjuta Num
tüübiklassi instants Mat22
tüübile.
instance Num a => Num (Mat22 a) where (Mat22 a b c d) + (Mat22 e f g h) = undefined (Mat22 a b c d) * (Mat22 e f g h) = undefined abs (Mat22 a b c d) = undefined negate (Mat22 a b c d) = undefined -- järgnevaid definitsioone pole vaja muuta fromInteger 0 = Mat22 0 0 0 0 fromInteger 1 = mempty fromInteger _ = error "fromInteger: Mat22" signum _ = error "signum: Mat22"
Korrektse lahenduse korral arvutab järgnevalt antud funktsioon n-inda Fibonacci arvu efektiivselt keerukusega {$ \mathcal{O}(\log n) $}, kasutades äsjadefineeritud maatriksite aritmeetikat:
fibNum :: (Integral a, Num b) => a -> b fibNum n = fn where Mat22 _ fn _ _ = (Mat22 1 1 1 0) ^ n