【问题标题】:No instance for (Fractional Int) arising from a use of `area'没有因使用“区域”而产生的 (Fractional Int) 实例
【发布时间】:2015-07-15 18:45:12
【问题描述】:

我是 Haskell 的新手,我正在编写一个计算函数极限的程序。因此,给定两个列表ab,一个增量dx = 0.001,以及积分限制lr,我想用方程递归地计算曲线下的面积: a1(x)^b1 + a2(x)^b2 + ... + an(x)bn 其中xlr 之间的所有值,每个值之间的增量为dx。我猜技术部分并不重要,但它有助于阅读代码:

import Text.Printf (printf)

-- This function should return a list [area].
solve :: Int -> Int -> [Int] -> [Int] -> [Double]
solve l r x y = [area l r x y]

area l r a b = if (l < r)
            then (calc l a b) * 0.001 + (area (l + 1) r a b)
            else (calc r a b) * 0.001


calc n (a:arest) (b:brest) = (fromIntegral(n) ^^ b) * fromIntegral(a) + (calc n arest brest)
calc n [] [] = 0


--Input/Output.
main :: IO ()

main = getContents >>= mapM_ (printf "%.1f\n"). (\[a, b, [l, r]] -> solve l r a b). map (map read. words). lines

上面的代码没有错误,但只要将area (l + 1) r a b 更改为area (l + 0.001) r a b,我就会收到以下错误消息:

No instance for (Fractional Int) arising from a use of `area'

我尝试创建一个新类并设置一个抽象类型,但没有奏效,还有其他想法吗?

【问题讨论】:

  • 尝试向所有顶级函数添加类型签名。例如,这也将帮助您澄清哪些参数应该是整数,哪些应该是双精度数。

标签: haskell recursion types casting functional-programming


【解决方案1】:

所以问题是Int 不是Fractional 类型。换句话说,它没有名为0.001 [note 1] 的值,但您已要求 Haskell 在您的代码中为您提供这样的值。

您提出这个请求是因为0.001 被提供给(+) 函数,并带有另一个类型为Int 的参数(在本例中为l)。这是一个问题,因为函数的类型为(+) :: (Num a) =&gt; a -&gt; a -&gt; a:换句话说,有很多不同的函数(+) 都具有a -&gt; a -&gt; a 的类型; Num 类型类中的每种类型 a 都存在这些函数之一。

由于我们知道函数的一个参数是Int,因此我们使用的是特定函数(+) :: Int -&gt; Int -&gt; Int。这就是为什么l + 0.001 变得奇怪的原因。

至于解决问题:您可能希望 lr 的类型为 Double(它们是数字的左右界限?)但如果您确定它们必须是Ints 那么你可能打算写fromIntegral l + 0.001

关于风格的旁注:Haskell 中的括号始终只是分组/优先级,函数的优先级高于运算符,运算符的优先级高于特殊形式(letcaseifdo),以及函数应用程序总是左关联或“贪婪的名义”:一个函数吃掉它前面的任何东西。你写的:

(fromIntegral(n) ^^ b) * fromIntegral(a) + (calc n arest brest)

最好写成:

fromIntegral a * fromIntegral n ^^ b + calc n arest brest

calc 周围的括号不是必需的(因为像 + 这样的运算符的优先级低于函数应用程序),na 周围的括号也不是必需的(因为这些子表达式是不可分割的块;fromIntegral(n)等同于fromIntegral (n) 等同于fromIntegral n)。

  1. 正如@dfeuer 在下面提到的:秘密地,当你写0.001 时,它没有明确的类型;而是在内部将其转换为fromRational 0.001,其中后者0.001 是确定类型Rational 的确定值,就像您编写4 时一样,它被转换为fromInteger 4,其中后4 是确定的确定类型Integer 的值。问题实际上是没有IntfromRational 函数,因为Int 不是定义fromRationalFractional 类型类的一部分。而且它不是该类型类的一部分,因为语言设计者更喜欢错误而不是无声的舍入/舍入分数。

【讨论】:

  • 在我看来“没有0.001 的实例”有点令人困惑。真正发生的是文字0.001 真正的意思是fromRational 0.001fromRational :: Fractional a =&gt; Rational -&gt; a,因此出现错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多