我有一个函数(*~)
。评估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 #-}
可以在这里保释我吗?如果是这样,它应该说什么? (我不清楚在规则查找匹配之前,分段语法会在多大程度上被贬低。)
答案 0 :(得分:5)
要触发此类优化,您需要确保您的函数内联。在{-# INLINE (*~) #-}
函数声明之前放置(*~)
pragma。我不能保证你会解决你的问题,但这是我看到它被接近的唯一方式。我之后会用"ghc-core"这样的工具检查生成的核心代码,以确保。
但是,您的问题实际上只是代码组成不正确的指示。你的功能正在做多个无关的事情。应该简单地考虑expensive y
,然后你的问题将被删除。即,使用模式应为x *~ expensive y
而不是x *~ y
。