Haskell - 无法匹配预期类型。帮助我理解这个问题

时间:2012-12-10 05:27:49

标签: haskell

我有以下类型类实例:

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

编辑:那很令人尴尬。

2 个答案:

答案 0 :(得分:2)

(数学上,我们通常不对这样的向量定义乘法(或除法) - 我们使用cross product或点积来组合两个向量。)

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

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

注意类型Vector -> Vector -> Scalar。结果类型为Scalar,因为当您对相乘的条目求和时,只有一个数字,而不是一个满数字的向量。这也意味着两个参数vector1vector2是向量,因此它们被写为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实例