部分评估右手操作员部分

时间:2015-10-21 20:00:24

标签: performance haskell ghc

我有一个函数(*~)。评估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 #-}可以在这里保释我吗?如果是这样,它应该说什么? (我不清楚在规则查找匹配之前,分段语法会在多大程度上被贬低。)

1 个答案:

答案 0 :(得分:5)

要触发此类优化,您需要确保您的函数内联。在{-# INLINE (*~) #-}函数声明之前放置(*~) pragma。我不能保证你会解决你的问题,但这是我看到它被接近的唯一方式。我之后会用"ghc-core"这样的工具检查生成的核心代码,以确保。

但是,您的问题实际上只是代码组成不正确的指示。你的功能正在做多个无关的事情。应该简单地考虑expensive y,然后你的问题将被删除。即,使用模式应为x *~ expensive y而不是x *~ y