Haskell 中的实例声明

发布于 2025-01-02 10:10:57 字数 1109 浏览 0 评论 0原文

我有这两个函数:

primes = sieve [2..] 
    where
        sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
isPrime number = number /= 1 && null [x | x <- takeWhile (\x -> x < (ceiling . sqrt) number) primes, mod number x == 0]

问题是,当我尝试加载包含这些函数的模块时,我看到以下错误消息:

[2 of 2] Compiling Main             ( euler37.hs, interpreted )

euler37.hs:6:70:
No instance for (RealFrac Int)
  arising from a use of `ceiling'
Possible fix: add an instance declaration for (RealFrac Int)
In the first argument of `(.)', namely `ceiling'
In the expression: ceiling . sqrt
In the second argument of `(<)', namely `(ceiling . sqrt) number'

euler37.hs:6:80:
No instance for (Floating Int)
  arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the second argument of `(.)', namely `sqrt'
In the expression: ceiling . sqrt
In the second argument of `(<)', namely `(ceiling . sqrt) number'

我真的不明白问题是什么,因为当我尝试创建一个小函数时来自一段代码,据我所知,它导致了这些错误,就在 ghci 中,就像 令 f 数 x = x < (上限 . sqrt)数量 我没有看到任何错误消息。

I have these two functions:

primes = sieve [2..] 
    where
        sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
isPrime number = number /= 1 && null [x | x <- takeWhile (\x -> x < (ceiling . sqrt) number) primes, mod number x == 0]

The thing is that when I'm trying to load module which contains those functions, I see following error message:

[2 of 2] Compiling Main             ( euler37.hs, interpreted )

euler37.hs:6:70:
No instance for (RealFrac Int)
  arising from a use of `ceiling'
Possible fix: add an instance declaration for (RealFrac Int)
In the first argument of `(.)', namely `ceiling'
In the expression: ceiling . sqrt
In the second argument of `(<)', namely `(ceiling . sqrt) number'

euler37.hs:6:80:
No instance for (Floating Int)
  arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the second argument of `(.)', namely `sqrt'
In the expression: ceiling . sqrt
In the second argument of `(<)', namely `(ceiling . sqrt) number'

I really can't understand what's the problem, because when I'm trying to make a small function from piece of code, which, as far as I understand, cause these errors, right in ghci, like
let f number x = x < (ceiling . sqrt) number
I don't see any error messages.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

土豪我们做朋友吧 2025-01-09 10:10:57

问题在于 primes 是一个整数列表(由于您使用了 mod),但 sqrt 对浮点数进行运算。如果你这样做 x < (ceiling . sqrt . fromIntegral) number,那么它就可以正常工作。 fromIntegral 只是将整数转换为任何其他数字类型:

fromIntegral :: (Integral a, Num b) => a -> b

在这种情况下,由于您没有指定要转换为的任何特定浮点类型,因此它将默认使用 Double 值来计算平方根。您可以通过将 fromIntegral 更改为 (fromIntegral :: Integer -> Float) 来指定其他类型。

您在 GHCi 中没有看到此错误的原因是您的条件很好;它只是适用于与您在这里使用的类型不同的类型。仅单独验证一段代码是否正确是不够的。为了让它通过类型检查器,它也必须在上下文中有意义。

您可能需要考虑使用整数平方根算法来提高准确性。

The problem is that primes is a list of Integers (due to your use of mod), but sqrt operates on floating-point numbers. If you do x < (ceiling . sqrt . fromIntegral) number, then it'll work fine. fromIntegral just converts an integral number into any other numeric type:

fromIntegral :: (Integral a, Num b) => a -> b

In this case, since you don't specify any specific floating-point type to convert to, it'll default to using Double values to compute the square root. You could specify another type by changing fromIntegral to something like (fromIntegral :: Integer -> Float).

The reason you don't see this error in GHCi is because your conditional is fine; it just works on different types to the ones you're using here. Just verifying that a piece of code is correct in isolation isn't enough; for it to pass the type checker, it has to make sense in context too.

You might want to consider using an integer square root algorithm for accuracy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文