Haskell重写规则和函数组合

Toy*_*rii 9 haskell rules ghc function-composition

为什么haskell需要多个重写规则,具体取决于函数组合技术和长度?有办法避免这种情况吗?

例如,给出以下代码......

{-# RULES
"f/f" forall a. f ( f a ) = 4*a
  #-}
f a = 2 * a
Run Code Online (Sandbox Code Playgroud)

这适用于

test1 = f ( f 1 )
Run Code Online (Sandbox Code Playgroud)

但是我们需要添加规则

test2 = f . f $ 1
Run Code Online (Sandbox Code Playgroud)

test3 = f $ f 1
Run Code Online (Sandbox Code Playgroud)

给我们留下以下规则

{-# 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
   #-}
Run Code Online (Sandbox Code Playgroud)

但是,当我们将这些组合在一起或使用其他形式的组合时,规则就不会触发.

test4 = f . f . f $ 1
test5 = f $ f $ f $ 1
test6 = f $ 1
Run Code Online (Sandbox Code Playgroud)

为什么是这样?我是否必须为每个可能的实现编写重写规则?

Dan*_*her 13

在许多情况下,规则不会触发,因为f在规则有机会触发之前,内联函数非常简单.如果延迟内联,

{-# INLINE [1] f #-}
Run Code Online (Sandbox Code Playgroud)

规则

{-# RULES "f/f" forall a. f (f a) = 4*a #-}
Run Code Online (Sandbox Code Playgroud)

应解雇所有这些案件(在这里与7.2.2和7.4.1一起工作).

原因是规则匹配器不是过于复杂,它只匹配具有规则的句法形式的表达式(不完全正确,规则体也经历了一些规范化).表达式f $ f 3f . f $ 4与规则的语法形式不匹配.要匹配规则,必须进行一些重写,($)并且(.)必须在规则与表达式匹配之前进行内联.但是,如果你不阻止f从简化器的第一阶段被内联,它就会被它的身体取代了相同的运行方式($)(.)内联,所以在接下来的迭代中,简化器看不到f了,它只能看到2*(2*x),这与规则不符.