2015-08-20 16 views
6

Kodu this kağıttan çalışıyorum. Çevirimimin daha ayrıntılı olduğu beni rahatsız ediyor. Bana göre, orijinal Miranda kadar özlü bir şey yapamayacak bir şey eksik.Miranda To Haskell - Geliştirilmiş sürümü nedir?

İşte Miranda:

fix :: qtree(*) -> qtree(*) 
fix(Leaf(x)) = Leaf(x) 
fix(Internal(nw, ne, sw, se)) = 
    merge(Internal(fix(nw), fix(ne), fix(sw), fix(se))) 
    where 
     merge(Internal (Leaf(x), Leaf(x), Leaf(x), Leaf(x))) = Leaf(x) 
     merge(other) = other 

Bildirimi merge arasında LHS. Dört yaprakların hepsinin aynı değere sahip olduğu durumu ele geçirir. Haskell'e doğru bir transliterasyon yapamazsınız, çünkü x'un çoklu tanımları ile ilgili bir şikayette bulunacağım. İşte benim sürümüm:

fix :: (Eq a) => QTree a -> QTree a 
fix (Leaf a) = Leaf a 
fix (Internal nw ne sw se) = 
    merge (Internal (fix nw) (fix ne) (fix sw) (fix se)) 
     where 
    merge [email protected](Internal (Leaf w) (Leaf x) (Leaf y) (Leaf z)) 
    | (w == x) && (x == y) && (y == z) = Leaf x 
    | otherwise      = internal 
    merge other = other 

Miranda kodunda olup bitenlere nasıl daha yakından yaklaşabilirim?

+2

"allEq [] = True; allEq (x: xs) = hepsi (x ==) xs' size biraz yardımcı olabilir. Nihayetinde lineer olmayan modeller Haskell'de değiller ve Miranda'dalar, öyle görünüyor, bu yüzden telafi etmek için fazladan bir iş yapmak zorunda kalacaksınız. Btw'den kurtulabilirsin | Aksi halde, bir sonraki denklem, bununla ilgilenir. – luqui

+0

Teşekkürler. Ben her zaman bir refleks olarak başka bir yere koydum. İyi yakalama. –

cevap

13

Referans olarak, bu gibi tekrarlanan bir adı olan bir desen, doğrusal olmayan olarak adlandırılır. Miranda bunları destekliyor ve Haskell yapmıyor. orijinal Haskell tasarım komitesi tarafından 1988 numaralı telefondan alınan bir tasarım ticareti. This thread, Haskell'de doğrusal olmayan modelleri desteklemediğine dair bazı ek mantığa sahiptir.

Ne yazık ki, bu Haskell'in desen eşleştirmesini kullanarak Miranda'ya gerçekten yaklaşamayacağınız anlamına gelir. Sahip olduğunuz gibi, eşitlik değerlerini açık bir şekilde karşılaştıran bazı kodlar yazmanız gerekir.

Eğer kolayca yapabilir bir gelişme sizin othewise durumda kurtulmak için: tüm korumalar başarısız olursa, bir sonraki modele hamle eşleşen deseni. Ayrıca, eşitlik kontrolünü biraz daha kısa yapabilirdiniz, ancak , tamamen kontrolünden kurtulamazsınız.

{-# LANGUAGE DeriveDataTypeable #-} 
import Data.Generics.Uniplate.Data 
import Data.Data(Data) 
import Data.Typeable(Typeable) 

data QTree a = Internal (QTree a) (QTree a) (QTree a) (QTree a) 
      | Leaf a 
      deriving (Data,Typeable -- for uniplate 
         , Eq, Show) 
-- not tested: 
fix :: (Data a, Eq a) => QTree a -> QTree a 
fix t = case map fix $ children t of 
    [email protected](Leaf w):xyz 
    | all (lw ==) xyz -> lw 
    _     -> t 

Bu basit jenerik artı yüklemler birleştirmek için yeteneğimizi:

fix :: (Eq a) => QTree a -> QTree a 
fix (Leaf a) = Leaf a 
fix (Internal nw ne sw se) = 
    merge (Internal (fix nw) (fix ne) (fix sw) (fix se)) 
    where merge (Internal (Leaf w) (Leaf x) (Leaf y) (Leaf z)) 
      | all (== w) [x, y, z] = Leaf x 
     merge other = other 
7

Buna benzer uniplate falan da Dörtlüağaç için gerçekten iyi çalıştığını bulabilirsiniz: Burada bana geliştirilmiş biraz görünen bir versiyonu case'daki desen eşleştirmesiyle, aslında, yinelenen özdeş dallar olan her iki sürüm hakkında beni rahatsız etti.