据我所知,我不会认为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
答案 0 :(得分:5)
(在整个帖子中进行了多次编辑并提供了更新信息)
在输出中,请注意Rule fired: Class op id2
行。这些是GHC为类型类实例自动创建的规则。此规则首先触发,因此您自己的规则永远不会有机会匹配。如果使用“-ddump-simpl-iterations”进行编译,则可以检查Class op规则是否在第一阶段触发,之后“to1”规则永远不会匹配。
这是一个解决方法。首先发表评论testThing1
,testThing1'
和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。