似乎无法在实例声明中将带有类型变量的类型表达式与需要显式类型的函数一起使用

0 haskell type-variables

无论如何,我在Haskell中找不到指定对' neg ' 的调用的类型:

instance Arith (V3 e) where neg x = vfmap (neg :: e->e)  x 
Run Code Online (Sandbox Code Playgroud)

(V3 e)e都是Arith的实例。在这里,我想称呼已经为类型'e'定义的' neg '。但这需要在“ neg ”调用上使用显式类型,并且没有表达式可以解析该类型吗?如果使用'e'的特定实例,就可以了。

vfmap (neg :: Dist->Dist ) x -这行得通(但不够通用) vfmap (neg :: e->e) x-没有使用'neg ' 引起的(Arith e1)实例- 使用'negvfmap neg e '引起的歧义类型变量'e0'阻止了约束'(Arith e0)”。 vfmap (neg :: Arith e => e->e) x-同上

{-# 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
Run Code Online (Sandbox Code Playgroud)

vfmap可以应用于(V2 e)或(V3 e),对于任何Arith元素类型的矢量,都是矢量类型。

当元素类型是类型变量时,这似乎无法编译,例如

• 由表达式类型签名引起的模棱两可的类型变量' e0 '阻止解决约束' (Arith e0) '。可能的解决办法:使用类型注释来指定应为“ e0 ”。

bra*_*drn 5

问题是在Haskell中,类型变量没有范围:也就是说,如果定义instance Arith (V3 e),则不能e在实例内部使用;如果您尝试这样做,GHC会将其解释为完全独立的类型变量。幸运的是,您可以{-# LANGUAGE ScopedTypeVariables #-}用来启用范围类型变量。如果这样做,您还会发现需要添加一个额外的Arith e =>约束。添加它可以使其成功编译。

(此外:在处理时MultiParamTypeClasses{-# LANGUAGE FunctionalDependencies #-}它也非常有用;我会在这种情况下亲自使用它,因为它消除了对的显式类型声明的需要neg。该想法是您定义class Functor c e | c -> e,这基本上意味着用于c确定的类型的类型e也一样。我在这里不做描述,但我强烈建议您查找。)