无论如何,我在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 ”。
问题是在Haskell中,类型变量没有范围:也就是说,如果定义instance Arith (V3 e),则不能e在实例内部使用;如果您尝试这样做,GHC会将其解释为完全独立的类型变量。幸运的是,您可以{-# LANGUAGE ScopedTypeVariables #-}用来启用范围类型变量。如果这样做,您还会发现需要添加一个额外的Arith e =>约束。添加它可以使其成功编译。
(此外:在处理时MultiParamTypeClasses,{-# LANGUAGE FunctionalDependencies #-}它也非常有用;我会在这种情况下亲自使用它,因为它消除了对的显式类型声明的需要neg。该想法是您定义class Functor c e | c -> e,这基本上意味着用于c确定的类型的类型e也一样。我在这里不做描述,但我强烈建议您查找。)