【问题标题】:Haskell Type Errors with division带有除法的 Haskell 类型错误
【发布时间】:2019-04-27 23:54:01
【问题描述】:

我有以下简单的程序来查找列表的平均值。我知道我的错误与类型推断有关,但我无法纠正它。我能得到一个更正和一个简单的解释吗?

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

【问题讨论】:

  • 您要查找哪个列表的平均值?您是否希望 average 成为一个函数,而不是 Float
  • 首先:average 不是Float。这是一个函数[Int] -> Float。另外,你应该在应用(/)时明确地将Ints 转换为Float

标签: haskell


【解决方案1】:

总结: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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-02
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 2013-12-18
    • 1970-01-01
    相关资源
    最近更新 更多