据我所知,我认为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
Run Code Online (Sandbox Code Playgroud)
这个例子:
{-# 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
Run Code Online (Sandbox Code Playgroud)
(在整个帖子中进行了多次编辑,包含更新信息)
在输出中,注意线条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
Run Code Online (Sandbox Code Playgroud)
你会看到这个输出:
$ ghc -c foo.hs
Rule fired: rewrite/to_id2'
Rule fired: rewrite/to_id2'
Rule fired: rewrite/to1'
Rule fired: rewrite/ez
Run Code Online (Sandbox Code Playgroud)
新规则现在正在触发而不是类op,这允许rewrite/to1'简化表达式.有趣的是,新规则是否出现rewrite/to1在规则列表的上方或下方并不重要.
我不知道为什么你的id2 (id2 a)规则不匹配,而不是id2 a.它看起来应该匹配(根据-dverbose-core2core),但事实并非如此.我仍然怀疑某种类型的GHC优先级错误,虽然我也看到了与ghc-7.4.1相同的行为,所以它不是4397.
| 归档时间: |
|
| 查看次数: |
421 次 |
| 最近记录: |