重写规则不会触发匹配多个实例方法的规则 [英] Rewrite rules not firing for rules matching multiple instance methods

查看:155
本文介绍了重写规则不会触发匹配多个实例方法的规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,我认为这不会有什么区别,id1和id2来自类型类,id1'和id2'不是。我正在使用最新的Haskell平台(GHC版本7.0.4和现在的7.4.1)运行ghc Rewrite,并且我希望1也能够启动。



<$重写
重写
编译RewriteProblems(Rewrite.hs,Rewrite.o)
被解雇的规则:重写/ ez'
被解雇的规则:重写/ to1'
被解雇的规则:重写/ ez
被解雇的规则:重写/ ez
被解雇的规则:类操作id2
被解雇的规则:类操作id2

举例:

  { - #OPTIONS_GHC -O -ddump-rule-firingings# - } 
模块RewriteProblems其中

{ - #RULES
rewrite / ezforall a。 id1 a = RDUnit
rewrite / to1forall 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

实例Ider重写D其中
{ - #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 
规则解雇:rewrite / to_id2'
规则解雇:rewrite / to_id2'
规则被解雇:重写/ to1'
被解雇的规则:重写/ ez

新规则是现在发射而不是类操作,它允许 rewrite / to1'来简化表达式。有趣的是,新规则在RULES列表中出现在 rewrite / to1 之上还是之下并不重要。



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

As far as I can tell I wouldn't think it would make any difference that id1 and id2 are from a type class and id1' and id2' are not. I am running "ghc Rewrite" with the latest Haskell Platform (with both GHC version 7.0.4 and now 7.4.1 too), and I expect to1 to also fire.

$ 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

the example:

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

解决方案

(several edits made throughout post with updated information)

In your output, notice the lines Rule fired: Class op id2. These are rules automatically created by GHC for type class instances. This rule is firing first, so your own rule never gets a chance to match. If you compile with "-ddump-simpl-iterations", you can check that the Class op rule fires in the first phase, after which your "to1" rule will never match.

Here's a bit of a workaround. First comment out testThing1, testThing1', and testThing2' so only testThing2 is compiled. This is the only function where "rewrite/to1" can fire, so it isolates the test case you're looking at. Next add another rule of the form:

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

and you'll see this output:

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

The new rule is now firing instead of the class op, which allows rewrite/to1' to simplify the expression. Interestingly, it doesn't matter if the new rule appears above or below rewrite/to1 in the list of RULES.

I don't know why your id2 (id2 a) rule isn't matching whereas id2 a does. It looks like it should match (according to -dverbose-core2core), but it isn't. I still suspect a GHC precedence bug of some type, although I also see the same behavior with ghc-7.4.1 so it isn't 4397.

这篇关于重写规则不会触发匹配多个实例方法的规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆