2017-03-06 17 views
14

Huet tarafından "The Fermuar" başlıklı makalede, aynı zamanda, fermuarların bir çeşidi olarak skarlardan bahseder. Haskell topluluğunda oldukça iyi bilinen fermuarlarla karşılaştırıldığında, yara izleri oldukça duyulmamış. Kâğıttaki ve internette bulabildiğim heryerde onlar hakkında çok az bilgi var.Yaralar ne için yararlıdır?

Bu yüzden sormam gerek, hiç işe yaramıyor mu yoksa yararlı oldukları bir şey mi var, ama çoğu insan bunları bilmiyor mu?

+1

Bu, ilgili söz konusu bazı bilgileri bulabilirsiniz: http://stackoverflow.com/questions/2990689/how-do-i-code-a-tree-of-objects-in-haskell-with- ebeveynlere-ve-çocuklara işaretçiler – Shersh

cevap

9

Bazı işlemleri daha verimli hale getirmek için ağaç türünde yalnızca küçük bir ayar var. numaralı kağıt üzerinde odaklanan kağıtlar (ha ha) ağaçlarına sahiptir. kağıttan kod OCaml içinde ama Haskell çevirmek çok basittir: kısaca Özetlemek gerekirse

data Rose a = Leaf a | Rose [Rose a] 

, fermuarlar fikri onun bağlamda bir veri yapısında pozisyon temsil etmektir. Bir gül ağacındaki bir düğümün bağlamı, düğümü ebeveynine ulaşmak için ağaca aldığınız yoldan ve düğümlerin kendisinin ulaşması için kardeşler listesinden aldığınız yoldan oluşur.

data Path a = Top | Node (Path a) [Rose a] [Rose a] 

data Pos a = Pos { focus :: Rose a, path :: Path a } 

Bu size right ve down yürüyerek gittiğiniz yerleri unutmadan ağaçtaki bir pozisyonda yakınlaştırmak ve sonra left çekilirken ve up uzaklaştırarak ağacı yeniden sağlar. up tanımlamadaki

right, down, left, up :: Pos a -> Maybe (Pos a) 
right (Pos _ Top) = Nothing 
right (Pos _ (Node _ _ [])) = Nothing 
right (Pos t (Node p ls (r:rs))) = Just $ Pos r (Node p (t:ls) rs) 

down (Pos (Leaf _) _) = Nothing 
down (Pos (Rose []) _) = Nothing 
down (Pos (Rose (t:ts)) p) = Just $ Pos t (Node p [] ts) 

left (Pos _ Top) = Nothing 
left (Pos _ (Node _ [] _)) = Nothing 
left (Pos t (Node p (l:ls) rs) = Just $ Pos l (Node p ls (t:rs)) 

up (Pos _ Top) = Nothing 
up (Pos t (Node p l r)) = Just $ Pos (Rose (l ++ t:r)) p 

bak. Şu anda odaklanmış olan düğüm ve kardeşleri t, l ve r alır ve bunları tek bir çocuk listesinde toplar. Baktığın hangi düğümü unutuyor. Buna göre down, mevcut odaklamanın en soldaki çocuğuna odaklanır. up'a gidip, daha önce odaklanmış olan düğüme geri dönmeniz gerekiyorsa, O (n) işleminin olduğu yer olan listeye geri dönmek için right adresine gidin.

Huet, ağaca 'yara izleri' bırakma düşüncesi, daha önce odaklanmış bir çocuğa dönmeyi daha uygun hale getirmekle ilgilidir. Rose yapıcısını kendi odağıyla bir liste fermuarıyla çocukların listesini değiştirerek donatıyor.

data SRose a = -- for "scarred rose" 
     SLeaf a 
    | SEmpty -- replaces (Rose []) 
    | SRose [SRose a] (SRose a) [SRose a] 

Path ve Pos türleri değişmeden kalır:

data SPath a = STop | SNode (SPath a) [SRose a] [SRose a] 
data SPos a = SPos { sfocus :: Rose a, spath :: SPath a } 

Şimdi, up gitmek ve sonra geri down, daha önce de aradıklarını unutmayın zaman.

up' (SPos _ STop) = Nothing 
up' (SPos t (SNode p l r)) = Just $ SPos (SRose l t r) p 

down' (SPos (SLeaf _) _) = Nothing 
down' (SPos SEmpty _) = Nothing 
down' (SPos (SRose l t r) p) = Just $ SPos t (SNode p l r) 
+0

İlginç. Ama yaramaz değil sadece fermuarları birleştirdi mi? Çünkü şimdi Rose Tree'deki listeyi liste fermuarıyla değiştirdiniz. –

+0

@TheRedFox Tam Olarak. –