如何在Haskell函数中使用类型类?
我现在试着用Haskell来教自己Haskell,所以为了测试我自己,我试着写一个函数,它获取一个数字列表并返回平均值如何在Haskell函数中使用类型类?,haskell,typeclass,type-declaration,Haskell,Typeclass,Type Declaration,我现在试着用Haskell来教自己Haskell,所以为了测试我自己,我试着写一个函数,它获取一个数字列表并返回平均值 listlen :: [a] -> Int listlen [] = 0 listlen (x:xs) = 1 + listlen xs avg :: (Num a) => [a] -> a avg [] = error "Cannot average list of length 0" avg l = ((foldr (+) 0 l) `div` (lis
listlen :: [a] -> Int
listlen [] = 0
listlen (x:xs) = 1 + listlen xs
avg :: (Num a) => [a] -> a
avg [] = error "Cannot average list of length 0"
avg l = ((foldr (+) 0 l) `div` (listlen l))
main = putStrLn (show (avg [1,2,3,4,5]))
但是,当我运行此代码时,会收到以下错误消息:
test.hs:7:10: error:
• Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
avg :: forall a. Num a => [Int] -> a
at test.hs:5:8
• In the expression: ((foldr (+) 0 l) `div` (listlen l))
In an equation for ‘avg’:
avg l = ((foldr (+) 0 l) `div` (listlen l))
• Relevant bindings include
avg :: [Int] -> a (bound at test.hs:6:1)
我一直在修补签名,唯一能让它工作的方法是将类型转换为实际类型,例如
avg::[Int]->Int
。我非常感谢您的建议。问题出在这里:
avg l = ((foldr (+) 0 l) `div` (listlen l))
listlen :: [a] -> Int
listlen [] = 0
listlen (x:xs) = 1 + listlen xs
div
是在Integral
s上定义的,而不仅仅是Num
s。另外,div
floors将显示结果。正常除法是(/)
,它是在分数上定义的
另外(更直接地)从这里:
avg l = ((foldr (+) 0 l) `div` (listlen l))
listlen :: [a] -> Int
listlen [] = 0
listlen (x:xs) = 1 + listlen xs
listlen
返回Int
,这使得div
的类型为Int->Int->Int
这应该起作用:
listlen :: (Num n) => [a] -> n
listlen [] = 0
listlen (x:xs) = 1 + listlen xs
avg :: (Fractional a) => [a] -> a
avg [] = error "Cannot average list of length 0"
avg l = foldr (+) 0 l / listlen l
或者,使用Prelude
中的某些功能:
avg :: (Fractional a) => [a] -> a
avg [] = error "Cannot average list of length 0"
avg l = sum l / fromIntegral (length l)
您测试过这个解决方案吗?我刚刚尝试了固定的代码,但仍然遇到类似的错误。length
返回一个Int
。我想你还没有学到关于测试的知识哦,天哪;;;