'Ormansızlaşma' bir programdan 'ağaçları' nasıl kaldırır?


12

Ormansızlaşmanın aynı anda nasıl bir liste içerdiğini ve ürettiğini anlıyorum (bir katlama ve bir açılma işlevinden - CodeReview'da bu iyi cevaba bakın ), ama bunu ' teknikten ' wikipedia girişi ile 'kaldırma' ağaçlar 'bir programdan.

Bir programın sözdizimsel ayrıştırma ağacına nasıl ayrıştırılabileceğini anlıyorum (bu doğru mu?), Ama programların bir tür sadeleştirme (bu?) İçin bu ormansızlaşma kullanımının anlamı nedir? Ve bunu koduma nasıl yaparım?

Yanıtlar:


9

Yatima2975 ilk iki sorunuzu ele almış gibi görünüyor, ben de üçüncü soruya geçmeye çalışacağım. Bunu yapmak için gerçekçi olmayan basit bir davayı ele alacağım, ancak eminim daha gerçekçi bir şey hayal edebileceksiniz.

n

type Tree = Leaf | Node Tree Tree

n

full : Int -> Tree
full n | n == 0 = Leaf
full n = Node (full (n-1)) (full (n-1))

Ve bir ağacın derinliği şu şekilde hesaplanır:

depth : Tree -> Int
depth Leaf = 0
depth (Node t1 t2) = 1 + max (depth t1) (depth t2)

depth (full n)nfulldepthdepth (full n)full_depth

full_depth : Int -> Int
full_depth n | n == 0 = 0
full_depth n = 1 + max (full_depth (n-1)) (full_depth (n-1))

Bu, tüm ağacın bellek tahsisini ve desen eşleştirme gerçekleştirme ihtiyacını önler, bu da performansı büyük ölçüde artırır. Ayrıca, optimizasyonu eklerseniz

max t t --> t

full_depth

Otomatik ormansızlaşma gerçekleştiren tek ana derleyici GHC'dir ve doğru hatırlarsam, bu sadece yerleşik işlevler oluştururken gerçekleştirilir (teknik nedenlerle).


Bu cevabı, esasen aynı bölgeyi kapsasalar bile, diğer cevaplardan daha formüle edildiğinden daha fazla aldım.
Cris Stringfellow

6

İ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

ralt 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 Listiçine ListFyinelemeli 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

unfoldListAynı ş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 Listve 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, deforestTreeeskisi gibi mekanik olarak yaratabiliriz .

(Genellikle, treeFolddaha 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:


Harika cevap, teşekkürler. Bağlantılar ve ayrıntılı örnek değerlidir.
Cris Stringfellow

3

Biraz kafa karıştırıcı, ancak ormansızlaşma (derleme zamanında) yaratılacak olan ara ağaçları (çalışma zamanında) ortadan kaldırmak için uygulanır. Ormansızlaşma soyut sözdizimi ağacının parçalarını kesmekle ilgili değildir (bu ölü dalların ortadan kaldırılması :-)

Seni atılmış olabilir başka bir şey listeleri olmasıdır vardır , sadece çok dengesiz olanlar ağaçlar!


Ah evet. Çok dengesiz!
Cris Stringfellow
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.