比较整数值和浮点值

发布于 2024-10-07 10:20:44 字数 1235 浏览 8 评论 0原文

所以,我正在学习 Haskell 的过程中,经常陷入类型/类型类相关的错误。一些非常明显的愚蠢错误,还有一些让我觉得 haskell 不适合我。无论如何,我有这段代码......

pfactors' ps n
    | p > (sqrt n) = []
    | m == 0 = p : (pfactors' ps q)
    | otherwise = pfactors' (tail ps) n where
        p = head ps
        (q, m) = divMod n p

pfactors = pfactors' primes

main = print $ pfactors 14

(一些背景:pfactors函数应该接受一个数字并返回一个素数列表,这些素数是给定数字的素数因子。primes是一个无限的质数列表)

,这给了我这个错误:

p47.hs:10:11:
    Ambiguous type variable `a' in the constraints:
      `Floating a' arising from a use of `pfactors'' at p47.hs:10:11-26
      `Integral a' arising from a use of `primes' at p47.hs:10:21-26
    Possible cause: the monomorphism restriction applied to the following:
      pfactors :: a -> [a] (bound at p47.hs:10:0)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction

现在我明白这是 p p < (sqrt n) 部分,因为它是唯一与 Floating 有关的部分。如果我将其更改为 p < n 一切正常,我得到了正确的答案。但我真的想检查平方根,那么我该怎么做呢?

顺便说一句,这不是家庭作业,如果感觉像是的话,这是我尝试解决projecteuler.net上的第47个问题,

感谢您的帮助。

并且,请不要给我上述项目欧拉问题的解决方案,我想尽可能自己做:)。谢谢。

So, I am in the process of learning Haskell, and am frequently falling to type/type-classes related errors. Some pretty obvious silly mistakes, and some that make me feel haskell isn't right for me. Anyway, I have this piece of code...

pfactors' ps n
    | p > (sqrt n) = []
    | m == 0 = p : (pfactors' ps q)
    | otherwise = pfactors' (tail ps) n where
        p = head ps
        (q, m) = divMod n p

pfactors = pfactors' primes

main = print $ pfactors 14

(Some background: the pfactors function is supposed to take a number and return a list of prime numbers, which are the prime factors of the given number. primes is an infinite list of prime numbers)

which gives me this error:

p47.hs:10:11:
    Ambiguous type variable `a' in the constraints:
      `Floating a' arising from a use of `pfactors'' at p47.hs:10:11-26
      `Integral a' arising from a use of `primes' at p47.hs:10:21-26
    Possible cause: the monomorphism restriction applied to the following:
      pfactors :: a -> [a] (bound at p47.hs:10:0)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction

Now I understood this is a problem with the p < (sqrt n) part, because it is the only part that has anything to do with Floating. If I change it to p < n everything works fine and I get the correct answer. But I really want to check with the square-root, so how do I do it?

And btw, this is not homework, if it feels like, it is my attempt at solving the 47th problem on projecteuler.net

Thanks for any help.

And, please don't give me the solution to the said project euler problem, I want to do it myself as much as I can :). Thanks.

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

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

发布评论

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

评论(3

北笙凉宸 2024-10-14 10:20:44

您的问题是...好吧...您无法比较整数值和浮点值:-) 您必须明确指示整数和浮点数之间的转换。 sqrt :: (Floating a) =>;一个-> a 函数适用于浮点数,但您主要处理整数,因此您不能免费使用它。尝试这样的操作:

pfactors' ps n
    | p > (floor $ sqrt $ fromIntegral n) = []
    | m == 0 = p : (pfactors' ps q)
    | otherwise = pfactors' (tail ps) n where
        p = head ps
        (q, m) = divMod n p

在这里,我们使用 fromIntegral :: (Integral a, Num b) =>;一个-> b 从整数转换为其他值,允许我们将其用作 sqrt 的参数。然后,我们说 floor 将浮点值转换回整数(请注意,这是向下舍入!)。

其次,我建议养成在顶级声明中添加类型签名的习惯。它不仅能让你更好地掌握语言,而且如果你不这样做,你可能会违反 单态限制

Your problem is that... well... you can't compare Integral and Floating values :-) You have to explicitly indicate the conversions between integers and floats. The sqrt :: (Floating a) => a -> a function works with floats, but you're dealing primarily in integers, so you don't get to use it for free. Try something like this:

pfactors' ps n
    | p > (floor $ sqrt $ fromIntegral n) = []
    | m == 0 = p : (pfactors' ps q)
    | otherwise = pfactors' (tail ps) n where
        p = head ps
        (q, m) = divMod n p

Here, we use fromIntegral :: (Integral a, Num b) => a -> b to convert from integer to something else, allowing us to use it as the argument to sqrt. Then, we say floor to convert our float value back to an integer (note that this rounds down!).

Second, I recommend getting into the habit of adding type signatures to your toplevel declarations. Not only will it give you a better grasp of the language, but if you don't, you may run foul of the monomorphism restriction.

沩ん囻菔务 2024-10-14 10:20:44

尽管已经提供了解决方案,但我想对正在发生的事情提供一些额外的说明。

特别是,类型类是NOT类型。不能有整数值或浮点值。这些不是类型,它们是类型类。这与面向对象的子类型不同。

Integral a => 这样的签名一个->一个-> a 并不意味着“接受两个 Integral 参数并返回一些 Integral 值的函数”。它的意思是“一个函数接受两个 a 类型的值,并返回一个 a 类型的值。此外,a 类型必须是 Integral 的实例。”两者之间的差异是显着的。请务必记住,参数和返回值的类型相同。 “a”在类型签名中不能改变其含义。

那么这一切意味着什么呢?

首先,没有先验要求类型不能同时是 Integral 和 Floating 的实例。如果您有这样的类型,则不需要转换。然而,每个类型类的语义使得单个类型很难以有意义的方式成为这两个类型的实例。

其次,您应该在谈论类型类时更加小心。它们与面向对象的子类型有根本的不同。由于概念上的差异,术语上也存在差异。准确使用术语有助于理解差异并与他人进行沟通。

那么我该如何表达这个问题呢?类似于“如何将 Integer 转换为 Floating 实例并返回?我需要使用 sqrt :: Floating a => a -> a 函数,并将其结果与,整数值。”

I want to provide some additional clarification of what's going on, even though the solution has already been provided.

In particular, type classes are NOT types. You can't have an Integral value or a Floating value. Those aren't types, they are type classes. This isn't like object-oriented subtyping.

A signature like Integral a => a -> a -> a doesn't mean "a function that takes two Integral arguments, and returns some Integral value." It means "A function that takes two values of type a, and returns a value of type a. Also, type a must be an instance of Integral." The differences between the two are significant. It's very important to remember that both arguments and the return value are the same type. "a" can't vary its meaning within a type signature.

So what does all this mean?

Well, first of all, there's no a priori requirement that a type can't be an instance of both Integral and Floating. If you had such a type, no conversions would be necessary. However, the semantic meaning of each of those type classes makes it hard for a single type to be an instance of both in a meaningful way.

Second, you should be a bit more careful in how you talk about type classes. They are fundamentally different from object-oriented subtyping. Because of the conceptual differences, there are also terminological differences. Being precise with your terminology helps to both understand the differences, and communicate them with others.

So how would I phrase the question, then? Something like "How do I convert an Integer to an instance of Floating and back? I need to use the sqrt :: Floating a => a -> a function on, and compare its result to, Integer values."

萌︼了一个春 2024-10-14 10:20:44

您已经得到了答案,但这可能有助于避免该功能中的类似问题:

http://www.haskell .org/haskellwiki/Converting_numbers

作为一个几乎完全从事动态类型语言背景的人,我有时也会遇到同样的问题,所以我养成了在写作时总是以签名开头的习惯Haskell 函数。它确实帮助我推理出我的期望和我出错的地方。

You already got your answer, but maybe this helps in avoiding similar problems in the feature:

http://www.haskell.org/haskellwiki/Converting_numbers

As someone whose background is almost exclusively in dynamically typed languages, I sometimes have the same problem, so I made it a habit to always start with the signature when writing a Haskell function. It really does help me in reasoning about what I expect and where I've gone wrong.

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