Cesta, krok 3
Zadáno ve středu 19. 5.
K odevzdání v pondělí 24. 5.
Z minula
- Přepsat
myProduct
asortInto
pomocí pattern matchingu a rekurze, bez použití listcomps, filteru, foldů a podobně. - Dovysvětlit pojmy typová třída, typ, a rozdíly mezi seznamem a tuplem (toto je spíše poznámka pro mne)
Sekce 1
Implementujte následující funkce — kde není řečeno jinak použijte manuální rekurzi (a pattern matching), nepoužívejte listcomps, map, filter atp.
myDrop
, která odstraní několik prvků z počátku seznamu> myDrop 0 ["a", "b", "c", "d"] ["a", "b", "c", "d"] > myDrop 2 [1, 2, 3, 4] [3, 4] > myDrop 10 [1, 2, 3, 4] []
myDropWhile
, která odstraní všechny prvky z počátku seznamu, pro které je pravdivý zadaný predikát> myDropWhile (\x -> x <= 2) [1, 2, 3, 4] [3, 4] > myDropWhile (\x -> x <= 2) [1, 2, 3, 1, 2, 3] [3, 1, 2, 3] > myDropWhile (\x -> const True x) "abcdefg" []
myGroup
, která dostane seznam prvků a "smrskne" k sobě ty, které jsou si rovny a jsou bezprostředně za sebou> myGroup [1, 1, 1, 2, 3, 3, 1] [[1, 1, 1], [2], [3, 3], [1]]
myMap
amyFilter
, které se chovají jakomap
afilter
. Konkrétně přepište svůj původnímyFilter
pomocí rekurze a patter matchingu.
Sekce 2
Implementujte následující funkce — kde není řečeno jinak použijte manuální rekurzi (a pattern matching), nepoužívejte listcomps, map, filter atp.
mySum
, která sečte seznam čísel> mySum [1, 2, 3] 6
myConcat
, která poskládá stringy se seznamu za sebe> myConcat ["abc", "def", "ghi"] "abcdefghi"
sumFromStartingPoint :: Int -> [Int] -> Int
jakomySum
, ale její první argument je už nějaký nahromaděný součet, který by se měl objevit ve finálním výsledku. Viz příklady.> sumFromStartingPoint 0 [1, 2, 3] -- s 0 se chová jako mySum 6 > sumFromStartingPoint 3 [1, 2, 3] -- místo 0 je náš 'základ' 3 9
Nepište celou funkci, ale doplňte následující implementaci:
sumFromStartingPoint :: Int -> [Int] -> Int sumFromStartingPoint base [] = base sumFromStartingPoint base (x:xs) = ...
myFold :: (a -> b -> b) -> b -> [a] -> b
, která se chová jakofoldr
.Prochází postupně seznam
[a]
a udržuje si mezivýsledekb
, přičemž tento mezivýsledek vždy zkombinuje s dalšíma
z procházeného seznamu. Až projde celé[a]
, vrátí poslední mezivýsledek. Inspirujte se svou funkcísumFromStartingPoint
—myFold
je vlastně její zobecněná verze, která nepočítá pouze s+
a sInt
, ale funguje s jakoukoli kombinující funkcía -> b -> b
.-- jako sumFromStartingPoint 0 -- (1:2:3:[]) -> (1+2+3+0) -> 6 > myFold (\x meziV -> x + meziV) 0 [1, 2, 3] 6 -- jako sumFromStartingPoint 8 -- (1:2:3:[]) -> (1+2+3+8) -> 14 > myFold (\x meziV -> x + meziV) 8 [1, 2, 3] 14 -- Zde, u mínus, je už důležité závorkování -- My se chováme jako foldR, takže závorkujeme zprava -- (1:2:3:[]) -> (1-(2-(3-0))) -- foldL by udělal (1:2:3:[]) -> (((1-0)-2)-3) > myFold (\x meziV -> x - meziV) 0 [1, 2, 3] 2
myFold1 :: (b -> b -> b) -> [b] -> b
, která se chová jakomyFold
, ale 'základ', tj. první mezivýsledek, který byl předtím daný jakob
, nebere zvenku jako argument, ale používá poslední prvek seznamu.Srovnání:
-- myFold ... 0: (1:2:3:[]) -> (1+(2+(3+0))) -> 6 -- myFold1 : (1:2:3:[]) -> (1+(2+3)) -> 6 -- myFold ... 0: (1:2:3:[]) -> (1-(2-(3-0))) -> 2 -- myFold1 : (1:2:3:[]) -> (1-(2-3))) -> 2
Napište nyní nové verze následujících funkcí (např s přidanou '
) pomocí myFold
nebo myFold1
:
mySum
myConcat
sumFromStartingPoint
myGroup