GHC Haskell中专门的导入函数
我现在正在处理一个项目,我正在处理Prim
typeclass,并且需要确保我编写的特定函数是专用的。 也就是说,我需要确保当我调用它时,我会得到一个专用版本的函数,其中Prim
字典被内联到特定的定义中,而不是在运行时传递。
幸运的是,这在GHC中是一个很好理解的东西。 你可以写:
{-# SPECIALIZE foo :: ByteArray Int -> Int #-}
foo :: Prim a => ByteArray a -> Int
foo = ...
而在我的代码中,这种方法工作正常。 但是,由于类型类是开放的,因此可能存在Prim
实例,但是在编写库Prim
不知道。 这给我带来了这个问题。 GHC用户指南的SPECIALIZE
文档提供了两种使用方法。 首先是将SPECIALIZE
放在定义的位置,就像我在上面的例子中所做的那样。 第二种方法是将SPECIALIZE
注置于另一个导入函数的模块中。 作为参考,用户手册提供的示例是:
module Map( lookup, blah blah ) where
lookup :: Ord key => [(key,a)] -> key -> Maybe a
lookup = ...
{-# INLINABLE lookup #-}
module Client where
import Map( lookup )
data T = T1 | T2 deriving( Eq, Ord )
{-# SPECIALISE lookup :: [(T,a)] -> T -> Maybe a
我遇到的问题是这在我的代码中不起作用。 该项目在github上,相关的行是:
bench/Main.hs
线24 src/BTree/Compact.hs
第149行 要运行基准测试,请运行以下命令:
git submodule init && git submodule update
cabal new-build bench && ./dist-newstyle/build/btree-0.1.0.0/build/bench/bench
当我运行基准时,有一部分输出结果为:
Off-heap tree, Amount of time taken to build:
0.293197796
如果我取消对BTree.Compact的第151行的评论,那么基准的那部分运行速度会快50倍:
Off-heap tree, Amount of time taken to build:
5.626834e-2
值得指出的是,有问题的函数modifyWithM
是巨大的。 它的实现超过100行,但我认为这不应该有所作为。 该文件声称:
...将f的定义标记为INLINABLE,以便GHC保证揭示展开,而不管它有多大。
所以,我的理解是,如果专注于定义网站的工作,应该始终可以专注于呼叫站点。 我很感谢来自那些比我更了解这种机器的人的任何见解,如果事情不清楚,我很乐意提供更多信息。 谢谢。
编辑:我已经意识到,在这篇文章中我链接到的git commit中,基准代码存在问题。 它重复插入相同的值。 但是,即使在解决这个问题之后,专业化问题仍然在发生。
链接地址: http://www.djcxy.com/p/33201.html