De les docs pour GHC 7.6 :
[Souvent, vous n'avez même pas besoin du pragma SPECIALIZE en premier lieu. Lors de la compilation d'un module M, l'optimiseur de GHC (avec -O) considère automatiquement chaque fonction surchargée de haut niveau déclarée dans M, et la spécialise pour les différents types auxquels elle est appelée dans M. L'optimiseur considère également chaque fonction surchargée importée INLINABLE, et la spécialise pour les différents types auxquels elle est appelée dans M.
et
De plus, étant donné un pragma SPECIALIZE pour une fonction f, GHC créera automatiquement des spécialisations pour toutes les fonctions surchargées en classe de type appelées par f, si elles sont dans le même module que le pragma SPECIALIZE, ou si elles sont INLINABLES ; et ainsi de suite, de manière transitive.
Ainsi, GHC devrait automatiquement spécialiser certains/plusieurs/tous( ?) fonctions marquées INLINABLE
sans un pragma, et si j'utilise un pragma explicite, la spécialisation est transitive. Ma question est la suivante : est-ce que le auto -spécialisation transitive ?
Plus précisément, voici un petit exemple :
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 spécialise l'appel à plus
mais est-ce que pas se spécialiser (+)
dans le Qux
Num
instance, ce qui nuit aux performances.
Cependant, un pragma explicite
{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}
résulte en transitif comme l'indique la documentation, donc (+)
est spécialisée et le code est 30x plus rapide (les deux compilés avec -O2
). Est-ce un comportement attendu ? Dois-je m'attendre à ce que (+)
pour être spécialisé de manière transitive avec un pragma explicite ?
UPDATE
Les documents relatifs à la version 7.8.2 n'ont pas changé et le comportement est le même, de sorte que cette question est toujours pertinente.