Download - Triedenie s banánmi, šošovkami a obálkami
Triedenie s banánmi, šošovkami a obálkamidnes už k triedeniu príde...
Erik Meijer, Maarten Fokkinga, Ross Paterson:Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire
Lex Augusteijn: Sorting morfizmuss, LNCS 1608, 3rd Int.School of Advanced Functional Programming, 1998
Schémy rekurzie: catamorfizmus anamorfizmus hylomorfizmus
List-anamorfizmusana (upwards as anabolismus)anamorfizmus alias lenses [( )], unfold
list-anamorfizmus je funkcia typu b -> [a]: deštruuj b, komponenty typu U rekurzívne konvertuj do [a], skombinuj výsledky typu [a] do výsledku typu [a].
list_ana1 :: (b->Bool) -> (b -> (a,b)) -> b -> [a]
list_ana1 p g b | p b = [] -- ak p b, tak končí rekuzia (terminátor)| otherwise = a:list_ana1 p g b'where (a,b') = g b -- g je nextor-- a je prvok do výsledného zoznamu -- b' je argument na rekurzívne volanie list_ana1
ziplist_ana1 :: (b->Bool) -> (b -> (a,b)) -> b -> [a]
zip1 ([1,2,3],[11,22,33])[(1,11),(2,22),(3,33)]
Definujme zip1 :: ([x],[y]) -> [(x,y)] pomocou list_ana1:
ujasnime si typy...b = ([x],[y])a = (x,y)p :: ([x],[y]) -> Boolg :: ([x],[y]) -> ( (x,y) , ([x],[y]) )
zip1 :: ([x],[y]) -> [(x,y)]zip1 = list_ana1 p g where
p ([],_) = True -- True, ak končí rekuziap (_,[]) = Truep (_,_) = Falseg (a:as, b:bs) = ((a,b), (as,bs))
-- (a,b) je prvok do výsledneho zoznamu-- as,bs je argument na rekurzívne volanie
list_ana1
iterate, mapDefinujte iterate1 :: (x -> x) -> x -> [x] pomocou list_ana1, aby
iterate1 f a = [a, f a, f f a, f f f a, ...]ujasnime si typy: b = a = x p :: (x -> Bool) - terminátor g :: x -> (x,x) - nextor
iterate1 f = list_ana1 p gwhere p _ = False -- never ending...g a = (a,f a) -- a je prvok do výsledneho zoznamu-- (f a) je argument na rekurzívne volanie list_ana1
map1 f = list_ana1 p gwherep [] = Truep _ = Falseg (a:as) = (f a, as) -- f a je prvok do výsledneho zozn.-- as je argument na rekurzívne volanie list_ana1
list_ana1 :: (b->Bool) -> (b -> (a,b)) -> b -> [a]
take 10 (iterate1 (+1) 5)[5,6,7,8,9,10,11,12,13,14]
List-coalgebraEither je súčet typov (union type) s tagmi Left a Right: data Either a b = = Left a | Right b
type List_coalg b a = b -> Either () (a, b) -- dosadíme Left () | Right (a, b)
List_coalg je p (terminátor) aj g (nextor) dokopy: ak list_coalg b = Left _, tak p b = True, ak list_coalg b = Right(a, b'), tak (a, b') = g b
list_ana2 :: List_coalg b a -> b -> [a]list_ana2 lca = ana where
ana u = case lca u ofLeft _ -> [] -- vtedy končíme, lca u = Left _Right (a,b') -> a : ana b' -- lca u = Right (a,b’), t.j. g b = (a,b’)
List-coalgebradestruct_count 0 = Left () – kedy končímedestruct_count n = Right (n,n-1) – n ide do výsledku
– na n-1 ide rekurziacount :: Integer -> [Integer]count = list_ana2 destruct_count
iterate2 f = list_ana2 (\a -> Right (a,f a))
map2 f = list_ana2 destruct_list wheredestruct_list [] = Left ()destruct_list (a:as)= Right(f a, as)
list_ana2 :: List_coalg b a -> b -> [a]
count 5[5,4,3,2,1]
take 10 (iterate2 (+1) 0)[0,1,2,3,4,5,6,7,8,9]
map2 (+1) [1..10][2,3,4,5,6,7,8,9,10,11]
List-coalgebra’ – iná syntaxtype List_coalg b a = b -> Either () (a, b) ==== b -> Left () | Right
(a,b)
data Either' x = True' | False' x – predefinujem náš vlastný Either
type List_coalg' b a = b -> Either' (a, b)type List_coalg' b a = b -> Either' (a, b) = b -> True' | False' (a,b)
list_ana2' :: List_coalg' b a -> b -> [a]list_ana2' lca = ana where
ana u = case lca u ofTrue' -> []False' (a,b') -> a : ana b'
count' = list_ana2' destruct_countwheredestruct_count 0 = True'destruct_count n = False' (n,n-1)
unfoldr (List.hs)data Either' x = True' | False' x data Maybe a = Nothing | Just a – v haskelli, Prelude.hs
deriving (Eq, Ord, Read, Show)
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]unfoldr f b = case f b of Just (a,b’) -> a : unfoldr f b’ Nothing -> []
count'' = unfoldr destruct_count wheredestruct_count 0 = Nothingdestruct_count n = Just (n,n-1)
iterate' f = unfoldr (\a -> Just (a, f a))
primeDefinujte prime ako anamorfizmusprime = sieve [2..] where
sieve = list_ana2 destruct_prime wheredestruct_prime (x:xs) = Right(x, [y | y <-xs, y `mod` x
> 0])
prime' = sieve [2..] wheresieve = list_ana2 ' destruct_prime where
destruct_prime (x:xs) = False'(x, [y | y <-xs, y `mod` x > 0])take 100 prime
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,...]Cvičenie-1: Definujte [1,2,4,8,...,2n, ...] ako anamorfizmus.Cvičenie-2: Definujte [1,3,7,15,..., 2n-1, ...] ako anamorfizmus.Cvičenie-3: Definujte [1,2, 6, 24,..., n!, ...] ako anamorfizmus.
insert-sortDefinujte insert-sort ako list-catamorfizmus (foldr)
insert_sort x = list_cata2 ([], insert) x whereinsert a [] = [a]insert a (x:xs) | a < x = a:x:xs
| otherwise = x : insert a xs
insert :: Int -> [Int] -> [Int]-- inak, cez foldr insert_sort' :: [Int] -> [Int] insert_sort' = foldr insert []
insert_sort [2,2,1,34,5,2,4,23,2,4][1,2,2,2,2,4,4,5,23,34]
Cvičenie-4: Viete definovať insert ako list-cata resp. ana-morfizmus ?
x:l
x l
x sort l
insert x (sort l)
destruct
recurse
insert
min-sort
selection_sort extra [4,3,2,4,2,1,3][4,3,2,4,2,1,3]
min_sort [4,3,2,4,2,1,3][1,2,2,3,3,4,4]
l
m l’
m sort l’
m:(sort l’)
extract minimum
recurse
construct
Cvičenie-4: Viete definovať remove ako list-cata resp. ana-morfizmus ?
Definujte min-sort ako list-anamorfizmus
selection_sort extract = list_ana2 select where
select [] = Left () select x= Right (extract x)-- dummy extract, prvyextra (x:xs) = (x,xs)
min_sort xs = selection_sort extract_min xs where
extract_min ls = (m, remove m ls) where m = minimum ls remove x [] = [] remove x (y:ls) | x == y = ls | otherwise = y : remove x ls
buble-sortDefinujme buble_sort ako selection_sort
buble_sort ls = selection_sort extract_buble ls whereextract_buble [x] = (x, [])extract_buble (x:ls) =
if x < y then (x,y:m) else (y,x:m) where (y,m) = extract_buble ls
-- definujme extract_buble ako cata-morfizmusbuble_sort' ls = selection_sort extract_buble ls
whereextract_buble (x:ls) = list_cata2 ((x,[]), bub) lsbub x (y,ls) = if x < y then (x,y:ls) else (y,x:ls)
buble_sort [4,3,2,4,2,1,3][1,2,2,3,3,4,4]
buble_sort' [4,3,2,4,2,1,3][1,2,2,3,3,4,4]
l
m l’
m sort l’
m:(sort l’)
buble
recurse
construct
Hurá na stromy… aby sme objavili nelinearne patterny rekuzie
data LeafTree x = Leaf x | Node (LeafTree x) (LeafTree x) deriving(Show, Read, Eq)-- príklad rekurzietree_sum (Leaf x) = xtree_sum (Node l r) = tree_sum l + tree_sum r
type Leaftree_alg x u = (x -> u, u -> u -> u)
leaftree_cata :: Leaftree_alg x u -> LeafTree x -> uleaftree_cata (fl, fs) = cata where
cata (Leaf x) = fl xcata (Node l r) = fs (cata l) (cata r)
– príkladtree_sum' = leaftree_cata (id,(+))
1
7 9
Ana na strometype Leaftree_coalg b a = b -> Either a (b,b)
leaftree_ana :: Leaftree_coalg b a -> b -> LeafTree aleaftree_ana lftca = ana where
ana t = case lftca t ofLeft l -> Leaf lRight (l,r)-> Node(ana l) (ana r)
Fib treefib_tree n
| n < 2 = Leaf 1| otherwise = Node (fib_tree (n-1)) (fib_tree (n-2))
– ako ana-morfizmusfib_tree' = leaftree_ana destruct_fib where
destruct_fib n | n < 2 = Left 1 | otherwise = Right (n-1, n-2)
fib_tree 4Node (Node (Node (Leaf 1) (Leaf 1)) (Leaf 1)) (Node (Leaf 1) (Leaf 1))
1
1 1
1 1
Hylo-morfizmus (ana . cata)
type Leaftree_hylo u x v = (Leaftree_coalg u x, Leaftree_alg x v)
leaftree_hylo :: Leaftree_hylo u x v -> u -> vleaftree_hylo (d, (fl, fs)) = hylo where
hylo t = case d t ofLeft l -> fl l -- (Leaf l) -> applikuj flRight (l,r) -> fs (hylo l) (hylo r) -- (Node l r) -> applikuj fs
fib = tree_sum' . fib_tree'
fib' = leaftree_hylo (destruct_fib, (id, (+))) Cvičenie-5: Definujte n! ako leaftree hylo-morfizmus.Cvičenie-6: Definujte xn ako leaftree hylo-morfizmus.
List-hylomorfizmuslist_hylo1 a c = (list_cata2 c) . (list_ana2 a)
prod = list_cata2 (1, (*))
fact3 = (list_cata2 (1, (*))) . (list_ana2 destruct_count)
fact3' = prod . count
fact3'' = list_hylo1 destruct_count (1, (*))
Cvičenie-7: Definujte xn ako list hylo-morfizmus.
merge-sortmerge_sort [] = []merge_sort xs = leaftree_hylo (select, (single, merge)) xs
wheresingle x = [x]merge (x:xs) (y:ys) | x < y = x:merge xs (y:ys)
| otherwise = y : merge (x:xs) ysmerge [] m = mmerge m [] = mselect [x] = Left xselect l = Right (split l)
split = list_cata2 (([],[]),f) wheref x (l,r) = (r, x:l)
split [1..10]([2,4,6,8,10],[1,3,5,7,9])
leaftree_ana select [1..4]Node ( Node (Leaf 4) (Leaf 2))
(Node (Leaf 3) (Leaf 1))
4 2 3 1
Binárny stromdata BinaryTree x = Nil | Branch x (BinaryTree x) (BinaryTree x)
type BinaryTree_alg x u = (u, x->u->u->u)
bintree_cata :: BinaryTree_alg x u -> BinaryTree x -> ubintree_cata (a,f) = cata where
cata Nil = acata (Branch x l r) = f x (cata l) (cata r)
type BinaryTree_coalg u x = u->Either () (x,u,u)
bintree_ana :: BinaryTree_coalg u x -> u -> BinaryTree xbintree_ana btca= ana where
ana t = case btca t ofLeft _ -> NilRight (x,l,r) -> Branch x (ana l) (ana r)
Cvičenie-8: Definujte bintree_hylo ako binarytree hylo-morfizmus.
3
1 8
7 9
quick-sortquick_sort l = bintree_hylo (split, ([], join)) l where
split [] = Left ()split (x:l) = Right (x, smaller, greater) where (smaller,greater) = partition' (<x) ljoin x l r = l ++ x : r
partition' p l = list_cata2 (([],[]),f) l wheref x (a, b) = if p x then (x:a,b) else (a,x:b)
Cvičenie-9: Cvičenie-10: Definujte n! ako bintree hylo-morfizmus.Cvičenie-11: Definujte xn ako bintree hylo-morfizmus.Cvičenie-12: Definujte hanojské veže ako bintree hylo-morfizmus.
para-morfizmustype List_para x u = (u, x->[x]->u->u)
list_para :: List_para x u -> [x] -> ulist_para (a,f) = para where
para [] = apara (x:l) = f x l (para l)
insert'' x = list_para ([x],combine) wherecombine a l rec | x < a = x:a:l
| otherwise = a:rec
insert_sort'' x = list_cata2 ([], insert'') x
Cvičenie-13: Definujte remove ako list para-morfizmus.