Haskell类型错误与除法

时间:2018-11-26 10:43:17

标签: haskell

我有以下简单的程序来查找列表的平均值。我知道我的错误与类型推断有关,但我无法更正。我可以对此进行更正和简单说明吗?

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

1 个答案:

答案 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