我有一个函数(*~)
.评估 x *~ y
的大部分成本来自检查第二个参数,大致如下:
(*~) :: a -> b d -> c d a
x *~ y = case y' of
Bar -> cheapFunction y' x
Baz -> cheapFunction2 y' x
Quux -> cheapFunction3 y' x
where
y' = expensive y
有什么方法可以说服 GHC 部分评估运算符部分,如
(*~ y)
?我试着像这样重写它:
(*~) = flip go
where
go y = let y' = expensive y
in case y' of
Bar -> cheapFunction y'
Baz -> cheapFunction2 y'
Quux -> cheapFunction3 y'
但这似乎没有帮助。我想这可能是因为
flip
在翻转之前需要它的所有论点?一种方法是翻转运算符本身,但当昂贵的操作数位于右侧时,它会更自然地读取,因为它与现有的符号对齐。
可以一个精心制作的
{-# RULE #-}
保释我在这里?如果是这样,它应该说什么? (我不清楚在规则查找匹配之前,分割语法将被脱糖多远,等等。)
最佳答案
要触发这样的优化,您需要确保您的函数被内联。放置{-# INLINE (*~) #-}
声明 (*~)
之前的 pragma功能。我不能保证它会解决你的问题,但这是我看到它被接近的唯一方式。我会使用 "ghc-core" 之类的工具检查生成的核心代码。之后确定。
但是,您的问题实际上只是代码组合不当的迹象。您的功能正在做多个不相关的事情。 expensive y
应该简单地排除它,那么您的问题将被删除。即,使用模式应该是 x *~ expensive y
而不是 x *~ y
.
关于performance - 部分评估右手操作符部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33268177/