重写规则不会触发匹配多个实例方法的规则
问题描述:
据我所知,我不认为这会使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
答
(整个后用更新的信息提出了一些修改)
在你的输出,注意线条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
新的规则,现在射击,而不是类运算,它允许rewrite/to1'
简化表达。有趣的是,新规则出现在规则列表中的rewrite/to1
之上还是之下并不重要。
我不知道为什么你的id2 (id2 a)
规则不匹配而id2 a
。它看起来应该匹配(根据-dverbose-core2core),但事实并非如此。我仍然怀疑某种类型的GHC优先级错误,尽管我也看到了与ghc-7.4.1相同的行为,所以它不是4397。
我刚刚安装了GHC的最新版本 - 版本7.4.1,现在我得到了和以前一样的输出。另外,是的,我意识到这些规则对输出没有任何影响 - 我只是通过这个测试用例来隔离我在一个更复杂的示例中遇到的问题。另外,我相信优先权在这里实际上是正常工作的......只是看着输出结果确实显示我的所有规则都是在这些出现之前尝试的。 – Akh 2012-03-22 04:18:41
你究竟如何确定你的规则是企图?我知道无法让GHC显示未应用的规则,或者在多个匹配的情况下使用哪个规则。你可以做的最好的是检查什么是真正被解雇的,在这种情况下是类操作规则。 – 2012-03-22 13:07:37
如果更改程序以使实例方法返回类似于错误的东西,即与RDUnit不同的东西,则重写规则应该让您处理,优化程序会在“testThing2”示例中为您留下错误值。我认为这个示例程序只是有点过分,不能清楚地显示问题。 – Anthony 2012-03-22 15:37:03