我有以下类型类实例:
type Scalar = Double
data Vector = Vector [Double] deriving (Show, Eq)
instance Num Vector where
(+) (Vector xs) (Vector ys) = Vector (zipWith (+) xs ys)
(-) (Vector xs) (Vector ys) = Vector (zipWith (-) xs ys)
(*) (Vector xs) (Vector ys) = Vector (zipWith (*) xs ys)
instance Fractional Vector where
(/) (Vector xs) (Vector ys) = Vector (zipWith (/) xs ys)
dot :: Vector -> Vector -> Vector
dot (Vector v1) (Vector v2) = sum $ v1 + v2
然而dot方法没有键入检查。我猜它不能使用+方法,即使它在Vector类上。
No instance for (Num [Double])
arising from a use of `+'
Possible fix: add an instance declaration for (Num [Double])
In the second argument of `($)', namely `v1 + v2'
In the expression: sum $ v1 + v2
In an equation for `dot':
dot (Vector v1) (Vector v2) = sum $ v1 + v2
编辑:那很令人尴尬。
答案 0 :(得分:2)
(数学上,我们通常不对这样的向量定义乘法(或除法) - 我们使用cross product或点积来组合两个向量。)
无论如何,如果您愿意,我们可以使用您的实例函数来定义点积:
dot :: Vector -> Vector -> Scalar
dot vector1 vector2 = let (Vector list3) = vector1 * vector2 in
sum list3
注意类型Vector -> Vector -> Scalar
。结果类型为Scalar
,因为当您对相乘的条目求和时,只有一个数字,而不是一个满数字的向量。这也意味着两个参数vector1
和vector2
是向量,因此它们被写为Vector somelist
。
我们在*
和vector1
使用了vector2
,其Vector
构造函数仍然完好无损,因为我们无法将双打列表相乘。在原始代码中,您尝试添加(或乘)双打列表,这将无效,因为您的实例仅定义了向量的加法和乘法,而不是原始[双]。
在let
子句中,我已采用此乘法的结果并将其与Vector list3
匹配。这意味着list3
是双打列表,所以我可以使用sum
函数; sum
在双打列表中定义,但在向量上没有定义,因此直接在sum
上使用vector1 * vector2
将无效。
示例:
> dot (Vector [1, 10, 100]) (Vector [1, 2, 3])
321.0
答案 1 :(得分:1)
问题在于
dot :: Vector -> Vector -> Vector
dot (Vector v1) (Vector v2) = sum $ v1 + v2
的类型错误,而不是
dot :: Vector -> Vector -> Double
dot (Vector v1) (Vector v2) = sum $ zipWith (*) v1 v2
另请注意,我将+
更改为*
,因为我认为您需要点积,或者
dot :: Vector -> Vector -> Double
dot v1 v2 = let Vector ls = v1 * v2 in sum ls
使用Num
Vector
实例