İlk olarak, listeler bir tür ağaçtır. Bir listeyi bağlantılı liste olarak temsil edersek , bu sadece her düğümü 1 veya 0 torunundan oluşan bir ağaçtır .
Ayrıştırma ağaçları sadece veri yapısı olarak ağaçların kullanılmasıdır. Ağaçlar, bilgisayar bilimlerinde sıralama, harita uygulama, ilişkilendirilebilir diziler vb. Gibi birçok uygulamaya sahiptir.
Genel olarak, liste, ağaçlar vb. Özyinelemeli veri yapılarıdır: Her düğüm bazı bilgiler ve aynı veri yapısının başka bir örneğini içerir. Katlama, düğümleri özyinelemeli olarak "aşağıdan yukarıya" değerlere dönüştüren tüm bu yapılar üzerinde yapılan bir işlemdir. Açma işlemi ters işlemdir, değerleri "yukarıdan aşağıya" düğümlere dönüştürür.
Belirli bir veri yapısı için, katlama ve açma işlevlerini mekanik olarak yapılandırabiliriz.
Örnek olarak, listeler alalım. (Yazdığı ve sözdizimi çok temiz olduğu için örnekler için Haskell kullanacağım.) Liste ya bir son ya da bir değer ve bir "kuyruk".
data List a = Nil | Cons a (List a)
Şimdi bir liste katladığımızı düşünelim. Her adımda, mevcut düğümün katlanması gerekiyor ve yinelemeli alt düğümlerini zaten katladık. Bu durumu şu şekilde temsil edebiliriz:
data ListF a r = NilF | ConsF a r
r
alt listenin katlanmasıyla oluşturulan ara değer nerede . Bu, listeler üzerinde katlama işlevi ifade etmemizi sağlar:
foldList :: (ListF a r -> r) -> List a -> r
foldList f Nil = f NilF
foldList f (Cons x xs) = f (ConsF x (foldList f xs))
Biz dönüştürmek List
içine ListF
yinelemeli onun alt liste üzerine katlanmasıyla ve sonra üzerinde tanımlı bir işlevi kullanmak ListF
. Bunu düşünürseniz, bu sadece standardın başka bir temsilidir foldr
:
foldr :: (a -> r -> r) -> r -> List a -> r
foldr f z = foldList g
where
g NilF = z
g (ConsF x r) = f x r
unfoldList
Aynı şekilde inşa edebiliriz :
unfoldList :: (r -> ListF a r) -> r -> List a
unfoldList f r = case f r of
NilF -> Nil
ConsF x r' -> Cons x (unfoldList f r')
Yine, bu sadece bir başka temsilidir unfoldr
:
unfoldr :: (r -> Maybe (a, r)) -> r -> [a]
( Maybe (a, r)
İzomorfik olduğuna dikkat edin ListF a r
.)
Bir ormansızlaşma işlevi de inşa edebiliriz:
deforest :: (ListF a r -> r) -> (s -> ListF a s) -> s -> r
deforest f u s = f (map (deforest f u) (u s))
where
map h NilF = NilF
map h (ConsF x r) = ConsF x (h r)
Sadece ara maddeyi bırakır List
ve katlama ve açma fonksiyonlarını birleştirir.
Aynı prosedür herhangi bir özyinelemeli veri yapısına uygulanabilir. Örneğin, düğümleri 0, 1, 2 veya 1- veya 0 dallı düğümlerde değerlere sahip torunları olan bir ağaç:
data Tree a = Bin (Tree a) (Tree a) | Un a (Tree a) | Leaf a
data TreeF a r = BinF r r | UnF a r | LeafF a
treeFold :: (TreeF a r -> r) -> Tree a -> r
treeFold f (Leaf x) = f (LeafF x)
treeFold f (Un x r) = f (UnF x (treeFold f r))
treeFold f (Bin r1 r2) = f (BinF (treeFold f r1) (treeFold f r2))
treeUnfold :: (r -> TreeF a r) -> r -> Tree a
treeUnfold f r = case f r of
LeafF x -> Leaf x
UnF x r -> Un x (treeUnfold f r)
BinF r1 r2 -> Bin (treeUnfold f r1) (treeUnfold f r2)
Tabii ki, deforestTree
eskisi gibi mekanik olarak yaratabiliriz .
(Genellikle, treeFold
daha rahat ifade ederiz :
treeFold' :: (r -> r -> r) -> (a -> r -> r) -> (a -> r) -> Tree a -> r
)
Ayrıntıları dışarıda bırakacağım, umarım desen açıktır.
Ayrıca bakınız: