0

我有以下类型类实例:

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

编辑:嗯,这很尴尬。

4

2 回答 2

2

(在数学上,我们通常不会像这样定义向量的乘法(或除法)——我们使用叉积或点积来组合两个向量。)

无论如何,如果您愿意,我们可以使用您的实例函数来定义点积:

dot :: Vector -> Vector -> Scalar
dot vector1 vector2 = let (Vector list3) = vector1 * vector2 in
   sum list3

注意类型Vector -> Vector -> Scalar。结果类型是Scalar因为当您将相乘的条目相加时,只有一个数字,而不是一个充满数字的向量。这也意味着这两个参数vector1vector2是向量,因此它们被写为Vector somelist.

我们使用*了 onvector1并且vector2它们的Vector构造函数仍然完好无损,因为我们不能将 Doubles 列表相乘。在您的原始代码中,您尝试添加(或相乘)双精度列表,但这是行不通的,因为您的实例仅定义向量的加法和乘法,而不是原始的 [Double]。

let子句中,我采用了这个乘法的结果并将其与Vector list3. 这意味着这list3 一个双打列表,所以我可以使用sum它的功能;sum是在 Doubles 列表上定义的,但不是在向量上定义的,因此sum直接使用 onvector1 * vector2是行不通的。

例子:

> dot (Vector [1, 10, 100]) (Vector [1, 2, 3])
321.0
于 2012-12-10T07:19:41.310 回答
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

另请注意,我将 更改+为 a*因为我假设您想要点积,或者

dot :: Vector -> Vector -> Double
dot v1 v2 = let Vector ls = v1 * v2 in sum ls

它使用Num实例Vector

于 2012-12-10T05:33:46.873 回答