从GHC 7.6 文档:
[Y]你通常甚至不需要SPECIALIZE附注。当编译一个模块M时,GHC的优化器(带有-O)会自动考虑在M中声明的每个顶层重载函数,并且专门针对它在M中调用的不同类型。优化器还会考虑每个导入的INLINABLE重载函数,并专门针对它在M中被称为的不同类型
和
此外,给定一个函数f的SPECIALIZE pragma,GHC将自动为f调用的任何类重载函数创建专门化,如果它们与SPECIALIZE pragma在同一个模块中,或者它们是INLINABLE; 等等。
因此,GHC应该自动专门化一些标记为INLINABLE 无标注的大部分/全部(?)功能,如果使用明确的附注,则专门化是传递性的。我的问题是:汽车专业化传递?
具体来说,这是一个小例子:
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 constructo
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,但并没有专门(+)的Qux Num杀死性能实例。
但是,一个明确的杂注
{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}
导致文档指出传递专业化,所以(+)是专门的,代码是30倍以上(都编译-O2)。这是预期的行为?我是否应该只希望(+)用一个明确的附注来传递?
相似问题