重写规则不会触发匹配多个实例方法的规则

时间:2012-03-21 19:11:52

标签: haskell

据我所知,我不会认为id1和id2来自类型类和id1'和id2'不是。我正在跑步" ghc重写"使用最新的Haskell平台(GHC版本7.0.4和现在版本7.4.1),我希望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

1 个答案:

答案 0 :(得分: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

新规则现在正在触发而不是类op,这允许rewrite/to1'简化表达式。有趣的是,如果新规则出现在规则列表中rewrite/to1之上或之下,则无关紧要。

我不知道为什么id2 (id2 a)规则不匹配而id2 a匹配。它看起来应该匹配(根据-dverbose-core2core),但事实并非如此。我仍然怀疑某种类型的GHC优先级错误,尽管我也看到了与ghc-7.4.1相同的行为,因此它不是4397