2012-03-21 5 views
8

Anlattığım kadarıyla, id1 ve id2'nin bir tür sınıfından ve id1 've id2' ​​'den farklı olmadığını düşünmüyorum. En son Haskell Platformu ile birlikte “ghc Rewrite” i çalıştırıyorum (hem GHC sürüm 7.0.4 hem de şimdi 7.4.1) ve ayrıca ateş etmeyi de bekliyorum.Birden çok örnek yöntemiyle eşleşen kurallar için kuralların yeniden yazılmadığını yeniden yazma

$ ghc Rewrite 
[1 of 1] Compiling RewriteProblems (Rewrite.hs, Rewrite.o) 
Rule fired: rewrite/ez' 
Rule fired: rewrite/to1' 
Rule fired: rewrite/ez 
Rule fired: rewrite/ez 
Rule fired: Class op id2 
Rule fired: Class op id2 

örnek:

{-# OPTIONS_GHC -O -ddump-rule-firings #-} 
module RewriteProblems where 

{-# RULES 
"rewrite/ez" forall a. id1 a = RDUnit 
"rewrite/to1" forall a. id2 (id2 a) = id1 a 
"rewrite/ez'" forall a. id1' a = RDUnit 
"rewrite/to1'" forall a. id2' (id2' a) = id1 a 
    #-} 

class Ider a where 
    id1 :: a -> a 
    id2 :: a -> a 

data RewriteD = RDUnit 

instance Ider RewriteD where 
    {-# INLINE[1] id1 #-} 
    {-# INLINE[1] id2 #-} 
    id1 a = RDUnit 
    id2 a = RDUnit 

testThing1 :: RewriteD 
testThing1 = id1 RDUnit 

testThing2 :: RewriteD 
testThing2 = id2 (id2 RDUnit) 

testThing1' :: RewriteD 
testThing1' = id1' RDUnit 

testThing2' :: RewriteD 
testThing2' = id2' (id2' RDUnit) 

{-# INLINE[1] id1' #-} 
{-# INLINE[1] id2' #-} 
id1' :: RewriteD -> RewriteD 
id2' :: RewriteD -> RewriteD 
id1' a = RDUnit 
id2' a = RDUnit 

cevap

5

(güncellenmiş bilgilerle yazı boyunca yapılan çeşitli düzenlemeler) sizin çıktısında

, çizgiler Rule fired: Class op id2 dikkat edin. Bunlar, sınıf sınıfı örnekleri için GHC tarafından otomatik olarak oluşturulan kurallardır. Bu kural ilk önce ateş ediyor, bu yüzden kendi kuralın asla eşleşme şansı olmaz. "-ddump-simpl-iterations" ile derlerseniz, Class op kuralının ilk aşamada işlediğini kontrol edebilirsiniz, bundan sonra "to1" kuralınız asla eşleşmeyecektir.

Burada biraz bir çözüm var. İlk yorum testThing1, testThing1' ve testThing2', bu nedenle sadece testThing2 derlenmiştir. Bu, "yeniden yaz/to1" işleminin yapılabildiği tek işlevdir, böylece baktığınız test vakasını ayırır. Sonraki formun başka bir kural ekleyin:

"rewrite/to_id2'" forall a. id2 a = id2' a 

ve bu çıktıyı görürsünüz: yeni kural yerine artık ifade kolaylığı rewrite/to1' verir sınıf op ait ateş ediyor

$ ghc -c foo.hs 
Rule fired: rewrite/to_id2' 
Rule fired: rewrite/to_id2' 
Rule fired: rewrite/to1' 
Rule fired: rewrite/ez 

. İlginç bir şekilde, yeni kuralın KURALLAR listesinde rewrite/to1'un üstünde veya altında görünmesi önemli değildir.

kuralı neden eşleşmiyor bilmiyorum, id2 a yapar. Eşleşmesi gerektiği gibi görünüyor (-dverbose-core2core'a göre), ama değil. Hala ghc-7.4.1 ile aynı davranışı görsem de bir tür GHC önceliği hatası olduğundan şüpheleniyorum, bu yüzden 4397 değil.

+1

Artık en son GHC sürümü - sürüm 7.4.1'i yükledim ve daha önce yaptığım gibi aynı çıktıyı aldım. Ayrıca, evet, bu kuralların çıktıda bir fark yaratmadığını fark ettim - bu test örneğini daha karmaşık bir örnekte aldığım problemi izole etmek için yaptım. Ayrıca, önceliğin burada doğru bir şekilde çalıştığına inanıyorum ... sadece çıktıya bakmak, tüm kurallarımın ortaya çıkmadan önce denendiğini gösteriyor. – Akh

+0

Kurallarınızın nasıl denendiğini tam olarak nasıl belirliyorsunuz? GHC'nin uygulanmayan kuralları veya birden fazla eşleşme durumunda hangi kuralın kullanıldığını göstermenin bir yolu olmadığını biliyorum. Yapabileceğin en iyi şey, gerçekte ateşin ne olduğunu kontrol etmektir, bu durumda bu, sınıf op kuraldır. –

+0

Programı değiştirirseniz, örnek yöntemi bir hata gibi bir şey döndürürse, yani, 'RDUnit' yeniden yazma kuralından farklı bir şey bırakmalıdır, iyileştirici, 'testThing2' örneğinde hata değeriyle birlikte kalmanızı sağlar. Bence bu örnek programın, problemi en açık şekilde ortaya koyması için biraz fazla kaynatılmış olduğunu düşünüyorum. – Anthony

İlgili konular