部分评估右手操作员部分
Partially evaluating right-handed operator sections
我有一个函数(*~)
。评估 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 (*~) #-}
编译指示放在 (*~)
函数声明之前。我不能向你保证它会解决你的问题,但这是我看到它被接近的唯一方式。之后我会使用 "ghc-core" 之类的工具检查生成的核心代码以确保。
但是,您的问题实际上只是代码组成不当的迹象。您的功能正在做多个不相关的事情。 expensive y
应该简单地从中排除,然后您的问题将被删除。即,使用模式应该是 x *~ expensive y
而不是 x *~ y
.
我有一个函数(*~)
。评估 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 (*~) #-}
编译指示放在 (*~)
函数声明之前。我不能向你保证它会解决你的问题,但这是我看到它被接近的唯一方式。之后我会使用 "ghc-core" 之类的工具检查生成的核心代码以确保。
但是,您的问题实际上只是代码组成不当的迹象。您的功能正在做多个不相关的事情。 expensive y
应该简单地从中排除,然后您的问题将被删除。即,使用模式应该是 x *~ expensive y
而不是 x *~ y
.