SPECIALIZE in the presence of constraints

Hallo List, I can't understand how pragma SPECIALIZE works in the presence of constraints. I have 2 modules, one which defines a general search framework, and one which implements it in a concrete context. The general module defines functions like: {-# SPECIALIZE pvQSearch :: Node (Game m) Move Int => Int -> Int -> Int -> Search (Game m) Move Int Int #-} pvQSearch :: Node m e s => s -> s -> Int -> Search m e s s pvQSearch a b c = do ... while the implementation uses concrete data types Move and Int (for e and s respectively) and defines instances and other types (like the polimorphic type Game m, where m is a monad). Node m e s is a class and the instance Node (Game m) Move Int is defined in the implementation module. From outside this construct is used by calling a generic search function, but giving parameters which match the implementation (i.e. with Move and Int for e and s, for example). Now what I don't understand: 1. how can the compiler (here ghc) know which function to expose as the correct generic search function? There must be two search functions generated, one generic and its specialization. Does the module export both and later the linker chooses the correct one, when the client module is known? 2. how can I know that the specialization is really used? When I have constraints, will the specializations be generated in the assumption that the constraint is matched? When will be this match checked? My problem is that, with or without specializations, the performance of the code is the same - so I doubt the specializations are used. Thanks, Nicu

On 26 September 2011 01:37, Nicu Ionita
1. how can the compiler (here ghc) know which function to expose as the correct generic search function? There must be two search functions generated, one generic and its specialization.
Yes, exactly. If you have: {-# SPECIALISE f :: Int -> Int #-} f :: Num a => a -> a f = ... Then GHC basically generates: f_spec :: Int -> Int f_spec = f f :: Num a => a -> a f = ... {-# RULES "f_spec" f = f_spec #-}
Does the module export both and later the linker chooses the correct one, when the client module is known?
The RULES mechanism chooses the correct one: when f applied to the specialised type arguments is seen, the generated RULE rewrites it to f_spec.
2. how can I know that the specialization is really used? When I have constraints, will the specializations be generated in the assumption that the constraint is matched? When will be this match checked?
The specialisation will be used if GHC can see that the generic function is applied to the correct type arguments. So for example a call to f inside another polymorphic function g (say g contains a use of f like: g = ... (f :: Int -> Int) ...) won't get specialised unless g it itself specialised or inlined.
My problem is that, with or without specializations, the performance of the code is the same - so I doubt the specializations are used.
GHC tells you which RULEs fired if you use -ddump-simpl or ghc-core. That might help you diagnose it, since if you see a rule fired for the specialisation then your code is probably using it. Failing that, inspecting the core output itself is always useful. Max
participants (2)
-
Max Bolingbroke
-
Nicu Ionita