2012-12-10 47 views
0

我有以下类型的类实例: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 

然而,点方法不键入检查。我猜它不能使用+方法,即使它在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

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

无论如何,我们可以使用您的实例函数来定义点的产品,如果你喜欢:

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

公告类型Vector -> Vector -> Scalar。结果类型为Scalar,因为当您对相乘的条目进行求和时,只有一个数字,而不是包含数字的向量。这也意味着vector1vector2这两个参数都是矢量,所以它们被写为Vector somelist

我们对vector1vector2有他们Vector构造仍然完好无损使用*,因为我们不能乘双打名单。在您尝试添加(或相乘)Doubles列表的原始代码中,这将不起作用,因为您的实例仅定义了向量上的加法和乘法,而不是原始[Double] s。

let子句中,我已将这个乘法的结果与Vector list3进行了匹配。这意味着list3的双打列表,所以我可以使用sum函数就可以了; sum在双精度列表上定义,但不在矢量上,因此直接在vector1 * vector2上使用sum将无法​​工作。

实施例:

> dot (Vector [1, 10, 100]) (Vector [1, 2, 3]) 
321.0 
+0

我不太明白为什么'sum'在你的函数中工作(你去哪里总结v3',其中'v3'是一个' Vector'),但我无法像这样调用Vector的总和:'sum(Vector [3 3 3])' –

+0

'v3'不是矢量,它是一个'[Double]',因为它是从一个'VECTOR'。 – huon

+0

@ DominicBou-Samra我已经扩展了一些解释并重新命名了变量以提供类型提示,所以现在我已经调用了'v3'' list3' - 这有帮助吗? – AndrewC

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

+0

喔屎。我怎么错过了。我在早期调试时更改了它,并且从未将其更改过。 –

+0

为什么我不能使用我定义的实例+函数?我可以在repl。这些定义都不起作用。 –

+0

@ DominicBou-Samra我不知道,我发布的代码适合我 –

相关问题