我有以下简单的程序来查找列表的平均值。我知道我的错误与类型推断有关,但我无法更正。我可以对此进行更正和简单说明吗?
average :: Float
average= uncurry (/) . sumlen
sumlen ::[Int]-> (Int,Int)
sumlen = foldl f (0,0)
where f (s,n) x = (s+x,n+1)
错误是:
• Couldn't match expected type ‘Float’
with actual type ‘[Int] -> Int’
• Probable cause: ‘(.)’ is applied to too few arguments
In the expression: uncurry (/) . sumlen
In an equation for ‘average’: average = uncurry (/) . sumlen
答案 0 :(得分:4)
摘要:Haskell是一种强类型语言。
您将sumlen
的类型强制为[Int] -> (Int,Int)
。
(/)
的类型为Fractional a => a -> a -> a
。
让我们进行类型检查。首先,我们将尝试推断其类型:
average = (uncurry (/)) . sumlen
uncurry :: (a -> b -> c) -> (a,b) -> c
(/) :: Fractional d => d -> d -> d
(.) :: (f -> g) -> (e -> f) -> e -> g
sumlen :: [Int] -> (Int,Int)
So:
e = [Int]
f = (Int,Int) = (a,b) = (d,d)
g = d = Int
average :: Fractional Int => [Int] -> Int
现在您告诉Haskell average :: Float
,而Haskell告诉您浮点数不是函数。这是您的错误。
如果删除注释,则会提示您没有实例Fractional Int
。这是因为您无法将1 / 2
表示或合理地近似为Int
。
该如何解决?
第0步是不要写下错误的类型签名(即average :: Float
)
您可以做的一件事是拥有一个更一般的sumlen。尝试使用Num a => [a] -> (a,a)
。您甚至可以拥有(Num a, Num b) => [a] -> (a,b)
。然后,您可以使用明智的类型average :: Fractional a => [a] -> a
您可以做的另一件事是从整数转换:
average xs = fromIntegral s / fromIntegral l where
(s,l) = sumlen xs