来自GHC 7.6 的文档:
[Y]你通常甚至不需要SPECIALIZE pragma.在编译模块M时,GHC的优化器(带-O)自动考虑在M中声明的每个顶级重载函数,并将其专门用于在M中调用它的不同类型.优化器还考虑每个导入的INLINABLE重载函数,并将其专门用于M中调用的不同类型.
和
此外,给定函数f的SPECIALIZE编译指示,GHC将自动为f调用的任何类型类重载函数创建特殊化,如果它们与SPECIALIZE编译指示位于同一模块中,或者它们是INLINABLE; 等等,过渡性的.
因此GHC应该自动专门化一些INLINABLE 没有编译指示标记的/大多数/所有(?)函数,如果我使用显式编译指示,则特化是可传递的.我的问题是:auto -specialization 是否具有传递性?
具体来说,这是一个小例子:
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
Run Code Online (Sandbox Code Playgroud)
Foo.hs:
module Foo (Qux(..), Foo(..), plus) where
import Data.Vector.Unboxed as U
newtype Qux r = Qux (Vector r)
-- …Run Code Online (Sandbox Code Playgroud) 我有一个代码体,使用monad来抽象实际实现是在ST还是IO内运行.由于内联和缺少类型类函数调用开销,删除额外的抽象层并且只是替换具体类型会产生巨大的加速(~4.5x).我想通过使用specialize pragma来获得一些性能,但是我从编译器得到了一个相当无意义的警告.我不能做一个简单的复制案例,因为这个简单的例子似乎有用,而且我不知道是什么导致我的实际程序有所不同.
基本上,我的程序执行此操作:
{-# LANGUAGE FlexibleInstances, RankNTypes #-}
module STImpl (runAbstractST, MonadAbstractIOST(..), ReaderST) where
import Control.Monad.Reader
import Control.Monad.ST
class Monad m => MonadAbstractIOST m where
addstuff :: Int -> m Int
type ReaderST s = ReaderT (Int) (ST s)
instance MonadAbstractIOST (ReaderST s) where
addstuff a = return . (a +) =<< ask
runAbstractST :: (forall s. ReaderST s a) -> a
runAbstractST f = runST $ runReaderT f 99
Run Code Online (Sandbox Code Playgroud)
和
module Main (main) where
import STImpl
import Control.Monad
{-# …Run Code Online (Sandbox Code Playgroud) 这是一个简单的例子,重现了我正在研究的一个真正的问题:
一个库模块:
module Lib where
class H h where
hash :: (S s)=> s -> h -> s
class S s where
mix :: s -> Int -> s
instance (H x, H y)=> H (x,y) where
hash s = \(x,y) ->
s `hash` x `hash` y
-- make this look "big":
`hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y
`hash` x `hash` y `hash` x `hash` y `hash` x `hash` y …Run Code Online (Sandbox Code Playgroud)