From the docs http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/pragmas.html#idp49866112对于 GHC 7.6:
[你]通常甚至一开始就不需要 SPECIALIZE pragma。编译模块 M 时,GHC 的优化器(使用 -O)自动考虑 M 中声明的每个顶级重载函数,并将其专门用于 M 中调用它的不同类型。优化器还考虑每个导入的 INLINABLE 重载函数,并将其专门用于 M 中称为的不同类型。
and
此外,给定函数 f 的 SPECIALIZE pragma,GHC 将自动为 f 调用的任何类型类重载函数创建特化,如果它们与 SPECIALIZE pragma 位于同一模块中,或者它们是 INLINABLE;等等,传递性地。
所以 GHC 应该自动专业化一些/大多数/全部(?) https://stackoverflow.com/questions/21071706/specialization-with-constraints功能标记INLINABLE
without一个编译指示,如果我使用显式编译指示,则专业化是传递的。我的问题是:
是个auto- 专业化传递?
具体来说,这是一个小例子:
Main.hs:
import Data.Vector.Unboxed as U
import Foo
main =
let y = Bar $ Qux $ U.replicate 11221184 0 :: Foo (Qux Int)
(Bar (Qux ans)) = iterate (plus y) y !! 100
in putStr $ show $ foldl1' (*) ans
Foo.hs:
module Foo (Qux(..), Foo(..), plus) where
import Data.Vector.Unboxed as U
newtype Qux r = Qux (Vector r)
-- GHC inlines `plus` if I remove the bangs or the Baz constructor
data Foo t = Bar !t
| Baz !t
instance (Num r, Unbox r) => Num (Qux r) where
{-# INLINABLE (+) #-}
(Qux x) + (Qux y) = Qux $ U.zipWith (+) x y
{-# INLINABLE plus #-}
plus :: (Num t) => (Foo t) -> (Foo t) -> (Foo t)
plus (Bar v1) (Bar v2) = Bar $ v1 + v2
GHC 专门呼吁plus
,但是确实not专门化(+)
in the Qux
Num
会降低性能的实例。
然而,一个明确的杂注
{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}
结果是及物的正如文档所示,专业化,所以(+)
是专门化的,代码速度快了 30 倍(均使用-O2
)。这是预期的行为吗?我应该只期待(+)
通过明确的编译指示来传递地专门化?
UPDATE
7.8.2 的文档没有改变,并且行为是相同的,所以这个问题仍然相关。