2012-03-21 87 views
8

據我所知,我不認爲這會使id1和id2來自類型類並且id1'和id2'不是。我正在使用最新的Haskell平臺(GHC版本7.0.4和現在的7.4.1)運行「ghc Rewrite」,我也希望1也能夠發射。重寫規則不會觸發匹配多個實例方法的規則

$ 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 

的例子:

{-# 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 

回答

5

(整個後用更新的信息提出了一些修改)

在你的輸出,注意線條Rule fired: Class op id2。這些是由GHC爲類型實例自動創建的規則。這條規則是先發射,所以你自己的規則永遠不會有機會匹配。如果使用「-ddump-simpl-iterations」進行編譯,您可以檢查Class op規則在第一階段觸發,之後您的「to1」規則永遠不會匹配。

這是一個解決方法。首先註釋掉testThing1testThing1'testThing2'因此只有testThing2被編譯。這是「rewrite/to1」可以觸發的唯一函數,因此它隔離了您正在查看的測試用例。接下來,添加形式的另一條規則:

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

,你會看到這樣的輸出:

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

新的規則,現在射擊,而不是類運算,它允許rewrite/to1'簡化表達。有趣的是,新規則出現在規則列表中的rewrite/to1之上還是之下並不重要。

我不知道爲什麼你的id2 (id2 a)規則不匹配而id2 a。它看起來應該匹配(根據-dverbose-core2core),但事實並非如此。我仍然懷疑某種類型的GHC優先級錯誤,儘管我也看到了與ghc-7.4.1相同的行爲,所以它不是4397

+1

我剛剛安裝了GHC的最新版本 - 版本7.4.1,現在我得到了和以前一樣的輸出。另外,是的,我意識到這些規則對輸出沒有任何影響 - 我只是通過這個測試用例來隔離我在一個更復雜的示例中遇到的問題。另外,我相信優先權在這裏實際上是正常工作的......只是看着輸出結果確實顯示我的所有規則都是在這些出現之前嘗試的。 – Akh 2012-03-22 04:18:41

+0

你究竟如何確定你的規則是企圖?我知道無法讓GHC顯示未應用的規則,或者在多個匹配的情況下使用哪個規則。你可以做的最好的是檢查什麼是真正被解僱的,在這種情況下是類操作規則。 – 2012-03-22 13:07:37

+0

如果更改程序以使實例方法返回類似於錯誤的東西,即與RDUnit不同的東西,則重寫規則應該讓您處理,優化程序會在「testThing2」示例中爲您留下錯誤值。我認爲這個示例程序只是有點過分,不能清楚地顯示問題。 – Anthony 2012-03-22 15:37:03