2016-03-04 57 views
1

我已经做了类型的类的实例时有问题,并提出列表类型的类的实例,但我得到它,我不明白使得列表中的类型类

class MyType a where 
listsum:: a->a->Double 

instance (Num a)=>MyType [a] where 
    listsum x y = sum $ zipWith (-) x y 

listsum返回错误单值但这是错误,我得到:

Could not deduce (a ~ Double) 
from the context (Num a) 
    bound by the instance declaration at b2.hs:4:10-28 
    `a' is a rigid type variable bound by 
     the instance declaration at b2.hs:4:10 
In the expression: sum $ zipWith (-) x y 
In an equation for `listsum': listsum x y = sum $ zipWith (-) x y 
In the instance declaration for `MyType [a]' 
Failed, modules loaded: none. 

如何解决这个问题?

回答

1

可以修改listsum:: a -> a -> Doublelistsum :: [a] -> [a] -> a及以上a而非[a]或宣布您的实例您可以修改您的实例从instance (Num a) => MyType [a]instance MyType [Double]

您可以通过采取表达式\x y -> sum $ zipWith (-) x y的类型来查看错误。你会发现它是Num a => [a] -> [a] -> a而不是Num a => [a] -> [a] -> Double,因为你的课程目前需要。

+0

@chi - 是的,这就是我得到的懒惰心理typechecking,现在修复... – sclv

2

让我们写下一些注释。

sum  :: (Num a, Foldable t) => t a -> a 
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 
(-)  :: Num a => a -> a -> a 

让我们推导出\ x y -> sum $ zipWith (-) x y的类型。

-- 1. Let's substitute (-) to zipWith: 

zipWith (-) :: Num a => [a] -> [a] -> [a] 

-- 2. Let's substitute `(zipWith (-))` to `sum`. We can't 
-- write it point free like in `zipWith (-)` case. So we add 
-- two extra params: 

(\ x y -> sum $ zipWith (-) x y) :: Num a => [a] -> [a] -> a 

[a]类型的listsum是:

listsum :: (Num a) => [a] -> [a] -> Double 

它需要的(Num a => a)和 回报Double东西两个列表。但是(\ x y -> sum $ zipWith (-) x y) 返回任何(Num a => a)。编译器不能确定 这个(Num a => a)将永远是Double。这就是为什么你 得到错误:

Could not deduce (a ~ Double) from the context (Num a) 

@sclv给你两个选择,以解决这个问题。另一个是 到MyType类更改为

class MyType a where 
    listsum:: [a] -> [a] -> a 

使得listsum(\ x y -> sum $ zipWith (-) x y)具有相同的类型。

它还为您提供了一个列表元素类型参数化listsum的机会。