Haskell 重写规则和函数组合
为什么 haskell 根据函数组合技术和长度需要多个重写规则?有办法避免这种情况吗?
例如,给定以下代码...
{-# RULES
"f/f" forall a. f ( f a ) = 4*a
#-}
f a = 2 * a
这适用于
test1 = f ( f 1 )
但是我们需要添加一个规则
test2 = f . f $ 1
并
test3 = f $ f 1
留下以下规则
{-# RULES
"f/f1" forall a. f ( f a ) = 4 * a
"f/f2" forall a. f . f $ a = 4 * a
"f/f3" forall a. f $ f $ a = 4 * a
#-}
但是,当我们将它们串在一起或使用某些其他形式的组合时,规则不会触发。
test4 = f . f . f $ 1
test5 = f $ f $ f $ 1
test6 = f $ 1
这是为什么呢?我是否必须为每种可能的实现编写重写规则?
Why does haskell require multiple rewrite rules depending on the function composition technique and length? Is there a way to avoid this?
For example, given the following code...
{-# RULES
"f/f" forall a. f ( f a ) = 4*a
#-}
f a = 2 * a
this works for
test1 = f ( f 1 )
however we need to add a rule for
test2 = f . f $ 1
and
test3 = f $ f 1
leaving us with the following rules
{-# RULES
"f/f1" forall a. f ( f a ) = 4 * a
"f/f2" forall a. f . f $ a = 4 * a
"f/f3" forall a. f $ f $ a = 4 * a
#-}
However, when we string these together or use some other forms of composition the rules do not fire.
test4 = f . f . f $ 1
test5 = f $ f $ f $ 1
test6 = f $ 1
Why is this? Do I have to write rewrite rules for every possible implementation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在许多情况下,规则不会触发,因为非常简单的函数
f
在规则有机会触发之前被内联。如果您延迟内联,则应在所有这些情况下触发该规则
(此处适用于 7.2.2 和 7.4.1)。
原因是规则匹配器并不过分复杂,它只匹配具有规则语法形式的表达式(不完全正确,规则主体也经历了一些规范化)。表达式
f $ f 3
或f 。 f$4
与规则的语法形式不匹配。为了使规则匹配,必须进行一些重写,在规则与表达式匹配之前必须内联($)
和(.)
。但是,如果您不阻止f
在简化器的第一阶段内联,它会在与($)
和相同的运行中被其主体替换(.)
是内联的,因此在下一次迭代中,简化器不再看到f
,它只看到2*(2*x)
,这不符合规则。The rule doesn't fire in many cases because the very simple function
f
is inlined before the rule had a chance to fire. If you delay the inlining,the rule
should fire for all these cases (worked here with 7.2.2 and 7.4.1).
The reason is that the rule matcher is not overly elaborate, it matches only expressions having the syntactic form of the rule (not entirely true, the rule body undergoes some normalisation too). The expressions
f $ f 3
orf . f $ 4
do not match the syntactic form of the rule. For the rule to match, some rewriting has to take place,($)
and(.)
have to be inlined before the rule matches the expression. But if you do not preventf
from being inlined in the first phase of the simplifier, it gets replaced by its body in the same run as($)
and(.)
are inlined, so in the next iteration, the simplifier doesn't seef
anymore, it only sees2*(2*x)
, which doesn't match the rule.我本以为这在默认情况下会起作用,但是您可以添加两个以上的重写规则来使 ./$ 简化为 lambdas/application,以便这将始终匹配:
测试:
输出:
这也适用于某些(但是由于其他重写规则,并非全部)更模糊的情况。例如,所有这些都将起作用:
I would have thought that this would work by default, but you can add two more rewrite rules to make ./$ reduced to lambdas/application, so that this will always match:
A test:
Output:
This will also work in some (but not all) more obscure cases, due to other rewrite rules. For example, all of these will work: