2011-06-11 31 views
7

İç içe geçmiş, karşılıklı özyinelemeli data structure var ve hesaplama pahalı değerlerini bazı düğümlerle ilişkilendirmek istiyorum. Aslında, bir Pandoc belgesindeki Blokları geçici olarak o blokta oluşan sözcüklerin listesine bağlamak istiyorum.Yerleşim veri yapısı?

  • o (kırılgan) kazan plaka kodu ve birçok yeni genişletilmiş Pandoc veri türünü oluşturmak için aşağı kaynar kelime listesini içerir Blok veri türü şekilde uzanan:

    Unattractive seçeneklerim önlemek istiyorum Blokları kelime listelerine eşleme; bloklar tuşları

ben bir çözüm arıyorum yönü verimli hizmet etmek çok karmaşık olarak optimal olan bu yüzden, genişletilmiş Blokları içeren bindirme veri yapısı çeşit olmakla birlikte temel veri tipleri bakir hala geniş Pandoc kütüphanelerini kullanabiliyorum. Ama belki de bu ... Düşünce Haskell Yolu değil

Hamiş 2011-06-12:

comments gösterdiği gibi, muhtemelen kısmen yanlış dayalı Harita yaklaşımın maliyet, abartmış varsayımlar. Gerçekten: "açık bir gerçekten daha aldatıcı bir şey yoktur".

Her halükarda, uzayabilir bir veri türünün nasıl oluşturulacağını gösterdiği için, hamarın cevabını kabul ediyorum.

Teşekkür

+0

İlişkileri düğümler arasında saklamak için bir 'Harita' kullanabilir misiniz? –

+0

@Don Stewart: Bloktan WordList'e bir Data.Map mı demek istiyorsunuz? Evet, ama benim endişem, anahtar olarak bir Blok, bir veri yapısı çok karmaşık olurdu. Tipik olarak, muhtemelen diğer Bloklar dahil olmak üzere tam bir paragrafı ve biçimlendirmesini temsil eder. – sleepyMonad

+2

Anahtar olarak saklanmadan önce bloğu karıştırın mı? – luqui

cevap

3

Bunu genişletilebilir olacak şekilde tasarlanmıştır değildi varolan veri türüne şeyler ekleyemezsiniz, bu nedenle bu tür kelime ilişkilendirmek için bir Map gibi bazı dış yapısına güvenmek zorunda gidiyoruz her bloğa listeler.

Veri türünü değiştirebilirseniz, ancak veri türündeki yinelemeyi genelleştirerek genişletilebilir hale getirebilirsiniz. Şimdi

data GenTree t = Leaf | Fork String t t 

, aldığımız orijinal gibi bir düz ağaç olması: Biz Tree yinelenen kullanımı için bir parametre ekleyebilir

data Tree = Leaf | Fork String Tree Tree 

: Diyelim ki böyle bir özyinelemeli veri türü var diyelim Bu türün sabit noktası:

data Fix a = Fix (a (Fix a)) 
type Tree = Fix GenTree 

Şimdi, her bir özyineleme sitesinde türü ek verilerle genişletebilirsiniz. Etiketli ağaçlar için bir türün nasıl yapılacağı aşağıda açıklanmıştır:

data Labelled t = Labelled Int (GenTree t) 
type LabelledTree = Fix Labelled 

strLength :: GenTree t -> Int 
strLength Leaf = 0 
strLength (Fork str _ _) = length str 

label :: Tree -> LabelledTree 
label (Fix tree) = Fix $ Labelled (strLength tree) (fmap label tree) 

instance Functor GenTree where 
    fmap f Leaf = Leaf 
    fmap f (Fork s l r) = Fork s (f l) (f r) 
+0

Bu cevabı anlamakta yarı yoldayım; gelişmiş tür sihirbazlık için zaten +1 ... türünde Ağacı = Fix GenTree = Düzeltme (GenTree (Fix GenTree)) = Düzeltme (Yaprak | Çatal Str (Fix GenTree) (Fix GenTree)) = Düzelt (Yaprak | Çatal Str Ağacı Ağacı) = Düzeltme Ağacı, Bu nedenle, Gentree Ağacı'na eşit olmalıdır. Bu, düğüm seviyesini tip seviyesinde bağlamak gibi bir şey mi? – sleepyMonad

+1

@sleepyMonad. Doğru, bir işlev tekrarlamak için ['fix'] (http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Function.html#v:fix) kullanarak benzerdir . Örneğin, özyinelemenin yerine bir parametreyle özyinelemeli bir faktoriyel fonksiyon alınız: “f f n = eğer n == 0 sonra 1 tane daha n * f (n-1)”. Şimdi, bunu düzeltmek için 'fix' kullanın: 'fix fac 10' – hammar

+1

@sleepyMonad: 'FlexibleContexts' ve 'UndecidableInstances' uzantıları ile yapılabilir. Örneğin, 'Show' için: türetme örneği (Show (a (Onar))) => Show (Fix a) '. (Bu ayrıca, derleyicinin benim için üretmesini sağlamak için 'StandaloneDeriving' kullanır.) – hammar