没有因使用“area”而产生的(Fractional Int)实例

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

我是 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'

我尝试制作一个新的 class 并使 a 成为抽象类型,但这没有用,还有其他想法吗?

所以问题是 Int 不是 Fractional 类型。换句话说,它没有一个叫做0.001的值[注1],但是你在你的代码中要求Haskell给你这样一个值。

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

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

至于解决问题:您可能希望 lr 属于 Double 类型(它们是数字可以在何处的左右边界?)但是如果您确定它们必须是 Int,那么您可能打算写 fromIntegral l + 0.001

关于样式的旁注:Haskell 中的括号始终只是 grouping/precedence,函数的优先级高于运算符,运算符的优先级高于特殊形式(letcase, if, do) 和函数应用总是左结合的或 "greedy nom":函数吃掉它前面的任何东西。你写了什么:

(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的定值。问题实际上是 Int 没有 fromRational 函数,因为 Int 不是定义 fromRationalFractional 类型 class 的一部分.而且它不是那种类型的一部分class,因为语言设计者更喜欢错误而不是沉默的 rounding/dropping 分数。