3. Haskelli praktikum
Selles praktikumis harjutame laiska väärtustamist ja arvutusi lõpmatute struktuuridega.
Näiteülesanded
aritmeetika
Väärtusta avaldised (1+2)+(3+4)
ja 1+(2+3)*(1+1)
.
funktsioon take
ft :: Int -> [Int] ft n = n : ft (n+1) take n _ | n <= 0 = [] take _ [] = [] take n (x:xs) = x : take (n-1) xs
Väärtusta avaldis take 2 (ft (2*5))
funktsioon takeWhile
ft :: Int -> [Int] ft n = n : ft (n+1) takeWhile _ [] = [] takeWhile p (x:xs) = if p x then x : takeWhile p xs else []
Väärtusta avaldis takeWhile (<11) (ft 10)
funktsioon foldr
foldr :: (a -> b -> b) -> b -> [a] -> b foldr _ a [] = a foldr f a (x:xs) = f x (foldr f a xs)
Väärtusta avaldis foldr (+) 1 [2,3]
Harjutusülesanded
ülesanne 0
Baastesti harjutamine: baas0.hs
ülesanne 1
(++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys)
Väärtusta avaldis [1+1] ++ [2+2]
ülesanne 2
foldl :: (b -> a -> b) -> b -> [a] -> b foldl _ a [] = a foldl f a (x:xs) = foldl f (f a x) xs
Väärtusta avaldis foldl (+) 1 [2,3]
ülesanne 3
map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs
Väärtusta avaldis map even [1,2]
ülesanne 4
(&&) :: Bool -> Bool -> Bool False && _ = False True && a = a r :: a -> [a] --- standardteegis nimegea repeat r x = x : r x foldr :: (a -> b -> b) -> b -> [a] -> b foldr _ a [] = a foldr f a (x:xs) = f x (foldr f a xs)
Väärtusta avaldis foldr (&&) True (r False)
ülesanne 5
(||) :: Bool -> Bool -> Bool True || _ = True False || a = a r :: a -> [a] --- standardteegis nimegea repeat r x = x : r x foldl :: (b -> a -> b) -> b -> [a] -> b foldl _ a [] = a foldl f a (x:xs) = foldl f (f a x) xs
Kirjuta avaldise foldl (||) True (r False)
väärtustamise neli esimest sammu.
Ülesanne 6
Kirjuta funktsioon vahelda
, mis genereerib lõpmatu listi, mis koosneb vaheldumisi kahest etteantud elemendist.
vahelda :: a -> a -> [a] vahelda x y = undefined
Ülesanne 7
Kirjuta funktsioon tsükkel
, mis genereerib lõpmatu listi, mis koosneb etteantud listi kordumistest.
tsükkel :: [a] -> [a] tsükkel xs = undefined
Ülesanne 8
Kirjuta abifunktsioon fibs'
, et antud fibs
oleks lõpmatu list Fibonacci arvudest.
fibs :: [Integer] fibs = fibs' 0 1 where fibs' a b = undefined
Ülesanded*
Haskelli laisa väärtustuse tähtis osa on n.n. graafireduktsioon, kus juhul kui funktsiooni argumente kasutatakse kahes eri kohas, viiakse/hoitakse avaldis where-kujul.
Näiteks
ruut :: Int -> Int ruut x = x*x
Väärtustame avaldis ruut (1+1)
.
ruut (1+1) ==> x*x where x = (1+1) (==> x*x where x = 2) ==> 2*2 ==> 4
Pane tähele, et kohe kui where muutuja on normaalkujul (ei saa enam lihtsustada) asendame selle väärtuse avaldisse.
Ülesanne 9
r x = x : r x take 0 _ = [] take n (x:xs) = x : take (n-1) xs
Väärtustage avaldis take 2 (r (1+1))
.
Ülesanne 10
Funktsioon seq :: a -> b -> b
sunnib esimese argumendi väärtustamist mille järel tagastatakse teine argument. Näiteks
seq x ((1+1)*x) where x = 2+2 ==> seq 4 (1+1)*4 ==> (1+1)*4 ==> 2*4 ==> 8 ((1+1)*x) where x = 2+2 ==> (2*x) where x = 2+2 ==> 2*4 ==> 8
Kasutades definitsiooni:
foldl' :: (b -> a -> b) -> b -> [a] -> b foldl' f a [] = a foldl' f a (x:xs) = seq z (foldl' f z xs) where z = f a x
Väärtusta foldl' (+) 1 [2,3]
.
Pane tähele, et foldl'
teine argument ei kasva väärtustamise käigus suureks/sügavaks avaldiseks.