我不明白为什么'dot'部分不起作用。
class Vector a where
add, minus, cross :: a -> a -> a
dot :: Num b => a -> a -> b
data Vector2D a = Vector2D a a deriving (Read)
instance Num a => Vector (Vector2D a) where
add (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 + x2) (y1 + y2)
minus (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
dot (Vector2D x1 y1) (Vector2D x2 y2) = x1*x2 + y1*y2
错误消息是:
Couldn't match expected type ‘b’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the instance declaration at example.hs:9:10
‘b’ is a rigid type variable bound by
the type signature for
dot :: Num b => Vector2D a -> Vector2D a -> b
at example.hs:12:3
Relevant bindings include
y2 :: a (bound at example.hs:12:37)
x2 :: a (bound at example.hs:12:34)
y1 :: a (bound at example.hs:12:20)
x1 :: a (bound at example.hs:12:17)
dot :: Vector2D a -> Vector2D a -> b (bound at example.hs:12:3)
In the first argument of ‘(*)’, namely ‘x1’
In the first argument of ‘(+)’, namely ‘x1 * x2’
我看一下点的类型,它是dot :: (Num b, Vector a) => a -> a -> b
。我怎样才能做对吗?
答案 0 :(得分:5)
问题是类型签名
dot :: Num b => a -> a -> b
表示dot
需要能够返回任何数字类型,无论向量类型是什么,而表达式x1*x2 + y1*y2
只返回放置的类型进入载体。
要解决此问题,您可以使用类型系列将单个标量类型连接到每个矢量类型:
{-# LANGUAGE TypeFamilies #-}
class Vector a where
type ScalarOf a
add, minus, cross :: a -> a -> a
dot :: a -> a -> ScalarOf a
data Vector2D a = Vector2D a a deriving (Read)
instance Num a => Vector (Vector2D a) where
type ScalarOf (Vector2D a) = a
add (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 + x2) (y1 + y2)
minus (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
dot (Vector2D x1 y1) (Vector2D x2 y2) = x1*x2 + y1*y2
另一种方法是使用多参数类型类,可能具有函数依赖性。
我还想提一下cross
产品基本上只对三维向量有意义。 (我听说你可以使它们适用于7个维度,或者通常为1维。)