问题
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
class PoC m where
type Wrapper m :: * -> *
wrap :: l -> Wrapper m l
I'm working with haskell-src-exts, and I want to upgrade my AST to have freshly generatable labels. Since I want to do it in an extensible fashion, I created an interface like the code above. However, code to upgrade the AST doesn't work. I have the following:
upgrade :: forall f m l. (PoC m, Functor f) => f l -> f (Wrapper m l)
upgrade x = fmap (wrap :: l -> Wrapper m l) x
But with or without the use of ScopedTypeVariables
, I get the same error:
/tmp/PoC.hs:10:19:
Could not deduce (Wrapper m ~ Wrapper m0)
from the context (PoC m, Functor f)
bound by the type signature for
upgrade :: (PoC m, Functor f) => f l -> f (Wrapper m l)
at /tmp/PoC.hs:9:12-69
NB: `Wrapper' is a type function, and may not be injective
The type variable `m0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Expected type: l -> Wrapper m0 l
Actual type: l -> Wrapper m l
In the first argument of `fmap', namely
`(wrap :: l -> Wrapper m l)'
In the expression: fmap (wrap :: l -> Wrapper m l) x
In an equation for `upgrade':
upgrade x = fmap (wrap :: l -> Wrapper m l) x
But I don't understand where GHC binds this m0
. Is "may not be injective" the core of the problem here?
回答1:
Non-injectivity is the problem, indeed. Injectivity would allow GHC to know that if f a ~ f b
then a ~ b
but since you can have two PoC m
instances with the same choice of Wrapper m
type it's hard to know what m
was after you've solved for what Wrapper m
is.
You should be able to fix it by adding an input term to wrap
which contains the m
type parameter. This can be a proxy argument which is never evaluated
data Proxy a = Proxy
class PoC m where
type Wrapper m :: * -> *
wrap :: proxy m -> l -> Wrapper m l
instance PoC () where
type Wrapper () = Maybe
wrap _ = return
aUnit :: Proxy ()
aUnit = Proxy
upgrade :: (PoC m, Functor f) => proxy m -> f l -> f (Wrapper m l)
upgrade aProxy x = fmap (wrap aProxy) x
来源:https://stackoverflow.com/questions/19838679/ambiguous-type-error-when-using-type-families-and-stv-is-not-helping