似乎无法在带有需要显式类型的函数的实例声明中使用带有类型变量的类型表达式
Cannot seem to use a type expression with a type variable in an instance declaration with a function needing an explicit type
无论如何,我在 Haskell 中找不到指定调用 'neg' 的类型:
instance Arith (V3 e) where neg x = vfmap (neg :: e->e) x
(V3 e) 和 e 都是 Arith 的实例。在这里我想调用已经为类型 'e' 定义的 'neg'。但这需要在 'neg' 调用中有一个显式类型,并且没有表达式可以解析该类型?如果使用 'e' 的特定实例,它很好。
vfmap (neg :: Dist->Dist ) x
-- 这行得通(但不够通用)
vfmap (neg :: e->e) x
-- (Arith e1) 没有因使用 ‘neg’ 而产生的实例
vfmap neg e
-- 因使用“neg”而产生的不明确类型变量“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
vfmap 可以应用于 (V2 e) 或 (V3 e ), 任意 Arith 元素类型向量的任一向量类型。
当元素类型是类型变量时,这似乎无法编译,例如
• 由表达式类型签名引起的不明确类型变量“e0”
防止解决约束“(Arith e0)”。
可能的修复:使用类型注释来指定“e0”应该是什么。
问题是在 Haskell 中,类型变量没有作用域:也就是说,如果您定义 instance Arith (V3 e)
,则不能在实例内部使用 e
;如果您尝试这样做,GHC 会将其解释为一个完全独立的类型变量。幸运的是,您可以使用 {-# LANGUAGE ScopedTypeVariables #-}
启用作用域类型变量。如果这样做,您还会发现需要添加一个额外的 Arith e =>
约束;添加这个将允许它成功编译。
(另外:在处理 MultiParamTypeClasses
时,{-# LANGUAGE FunctionalDependencies #-}
也非常有用;我个人会在这种情况下使用它,因为它消除了对 [= 的显式类型声明的需要16=]。这个想法是你定义 class Functor c e | c -> e
,这基本上意味着 c
的类型也决定了 e
的类型。我不会在这里描述,但是我会 高度 鼓励你查一查。)
无论如何,我在 Haskell 中找不到指定调用 'neg' 的类型:
instance Arith (V3 e) where neg x = vfmap (neg :: e->e) x
(V3 e) 和 e 都是 Arith 的实例。在这里我想调用已经为类型 'e' 定义的 'neg'。但这需要在 'neg' 调用中有一个显式类型,并且没有表达式可以解析该类型?如果使用 'e' 的特定实例,它很好。
vfmap (neg :: Dist->Dist ) x
-- 这行得通(但不够通用)
vfmap (neg :: e->e) x
-- (Arith e1) 没有因使用 ‘neg’ 而产生的实例
vfmap neg e
-- 因使用“neg”而产生的不明确类型变量“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
vfmap 可以应用于 (V2 e) 或 (V3 e ), 任意 Arith 元素类型向量的任一向量类型。
当元素类型是类型变量时,这似乎无法编译,例如
• 由表达式类型签名引起的不明确类型变量“e0” 防止解决约束“(Arith e0)”。 可能的修复:使用类型注释来指定“e0”应该是什么。
问题是在 Haskell 中,类型变量没有作用域:也就是说,如果您定义 instance Arith (V3 e)
,则不能在实例内部使用 e
;如果您尝试这样做,GHC 会将其解释为一个完全独立的类型变量。幸运的是,您可以使用 {-# LANGUAGE ScopedTypeVariables #-}
启用作用域类型变量。如果这样做,您还会发现需要添加一个额外的 Arith e =>
约束;添加这个将允许它成功编译。
(另外:在处理 MultiParamTypeClasses
时,{-# LANGUAGE FunctionalDependencies #-}
也非常有用;我个人会在这种情况下使用它,因为它消除了对 [= 的显式类型声明的需要16=]。这个想法是你定义 class Functor c e | c -> e
,这基本上意味着 c
的类型也决定了 e
的类型。我不会在这里描述,但是我会 高度 鼓励你查一查。)