Cannot seem to use a type expression with a type variable in an instance declaration with a function needing an explicit type
I cannot find anyway in Haskell to specify the type of the call to 'neg':
instance Arith (V3 e) where neg x = vfmap (neg :: e>e) x
(V3 e) and e are both instances of Arith. Here I want to call the 'neg' already defined for the type 'e'. But this requires an explicit type on the 'neg' call and no expression can resolve the type? If use a specific instance of 'e', it si fine.
vfmap (neg :: Dist>Dist ) x
 this works (but is not general enough)
vfmap (neg :: e>e) x
 No instance for (Arith e1) arising from a use of ‘neg’
vfmap neg e
 Ambiguous type variable ‘e0’ arising from a use of ‘neg’
prevents the constraint ‘(Arith e0)’ from being solved.
vfmap (neg :: Arith e => e>e) x
 ditto
{# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, InstanceSigs #}
data Dist = Inch Float deriving (Show)
class Arith a where
neg :: a>a
instance Arith Dist where
neg (Inch x) = Inch (x)
data V2 e = V2 e e deriving (Show)
data V3 e = V3 e e e deriving (Show)
class VMap c e where
vfmap :: (e>e)>c>c
instance VMap (V2 e) e where
vfmap f (V2 x1 x2) = V2 (f x1) (f x2)
instance VMap (V3 e) e where
vfmap f (V3 x1 x2 x3) = V3 (f x1) (f x2) (f x3)
 2 & 3 point vectors should also be Arith
instance Arith (V2 Dist) where
neg x = vfmap (neg :: Dist>Dist) x  works, but must have type on neg
instance Arith (V3 e) where
neg x = vfmap (neg :: Arith e => e>e) x  nothing here seems to work
vfmap can be applied to a (V2 e) or a (V3 e), either vector type for a vector of any Arith element type.
This won't seem to compile when the element type is a type variable, e.g.
• Ambiguous type variable ‘e0’ arising from an expression type signature prevents the constraint ‘(Arith e0)’ from being solved. Probable fix: use a type annotation to specify what ‘e0’ should be.
1 answer

The issue is that in Haskell, type variables aren't scoped: that is, if you define
instance Arith (V3 e)
, you can't usee
inside the instance; if you try to, GHC will interpret it as being a completely separate type variable. Luckily, you can use{# LANGUAGE ScopedTypeVariables #}
to enable scoped type variables. If you do that, you'll also find you need to add an extraArith e =>
constraint; adding this will allow it to compile successfully.(Aside: when dealing with
MultiParamTypeClasses
,{# LANGUAGE FunctionalDependencies #}
is also incredibly useful; I would personally use it in a case like this, as it removes the need for explicit type declarations forneg
. The idea is that you define insteadclass Functor c e  c > e
, which basically means that the type forc
determines the type fore
as well. I won't describe it here, but I would highly encourage you to look it up.)