我创建了一个类型类,并列出了类型类的实例,但是我收到了一个我不明白的错误
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.
我该如何解决这个问题?
答案 0 :(得分: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
listsum
的{{1}}类型为:
[a]
它需要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
的机会。
答案 1 :(得分:1)
您可以将listsum:: a -> a -> Double
修改为listsum :: [a] -> [a] -> a
并将您的实例声明为a
而不是[a]
或您可以从{修改您的实例{1}}至instance (Num a) => MyType [a]
。
只需获取表达式instance MyType [Double]
的类型即可看到错误。您会看到,您的班级目前需要\x y -> sum $ zipWith (-) x y
而不是Num a => [a] -> [a] -> a
。