I'm messing around with the SPECIALIZE
pragma while trying to find a solution to this problem.
I came up with this example:
{-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving #-}
import Data.Vector
import qualified Data.Vector.Generic as V
class Foo a
newtype Phantom m = T Int deriving (Show)
instance (Foo m) => Num (Phantom m)
f :: (Num r, V.Vector v r) => v r -> v r -> v r
{-# SPECIALIZE f :: (Foo m) => Vector (Phantom m) -> Vector (Phantom m) -> Vector (Phantom m) #-}
f x y = V.zipWith (+) x y
main = print "hello"
which fails to compile (GHC 7.6.2) because
Forall'd constraint `Foo m' is not bound in RULE lhs
.
Googling only turned up a couple of GHC bug reports from years ago. I didn't see anything about "forall'd constraints" while reading about SPECIALIZE
or RULE
. My specialize signature does seem less polymorphic than the original, and it satisfies the "if-and-only-if" rule.
replace with
{-# SPECIALIZE f :: (Num (Phantom m)) => Vector (Phantom m) -> Vector (Phantom m) -> Vector (Phantom m) #-}
and it will work. The r
in Num r
is Phantom m
not m
, thus you can't add the constraint Num m
. This is logical--Num (Phantom m)
does not imply Num m
and you could get other instances under the open world assumption.
EDIT: You actually don't need any constraint at all in this case
{-# SPECIALIZE f :: Vector (Phantom m) -> Vector (Phantom m) -> Vector (Phantom m) #-}
anyway, the basic problem if I understand what you are trying to do is that you can't constrain when you perform an optimization based on phantom type parameters.