因此,我正处于学习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(一些背景知识:假设pfactor函数接受一个数字并返回一个质数列表,质数是给定数字的质因数。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 < (sqrt n)部件的问题,因为它是唯一与Floating有关的部件。如果我把它改成p < n,一切都很好,我得到了正确的答案。但是我真的想用平方根检查,那我该怎么做呢?
顺便说一句,这不是家庭作业,如果感觉像是,这是我在projecteuler.net上解决第47个问题的尝试
谢谢你的帮助。
并且,请不要给我解决上述项目euler问题的方法,我想尽可能自己做:)。谢谢。
发布于 2010-12-11 13:16:03
你的问题是...好吧..。你不能比较整数值和浮点值:-)你必须显式地指出整数和浮点数之间的转换。sqrt :: (Floating a) => 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) => a -> b将整数转换为其他值,允许我们将其用作sqrt的参数。然后,我们使用floor将我们的浮点值转换回一个整数(注意这个向下舍入!)。
其次,我建议养成将类型签名添加到顶层声明的习惯。它不仅会让你更好地掌握语言,而且如果你不这样做,你可能会与monomorphism restriction发生冲突。
发布于 2010-12-11 16:50:53
尽管已经提供了解决方案,但我还是想对正在发生的事情提供一些额外的说明。
特别是,类型类是而不是类型。不能有整数值或浮点值。这些不是类型,它们是类型类。这与面向对象的子类型不同。
像Integral a => a -> a -> a这样的签名并不意味着“一个接受两个整型参数并返回一些整数值的函数”。它的意思是“一个函数接受两个a类型的值,并返回一个a类型的值。另外,a类型必须是Integral的实例。”两者之间的差异是显著的。记住,参数和返回值是同一类型,这一点非常重要。"a“不能在类型签名中改变其含义。
那么这一切意味着什么呢?
首先,没有先验要求,一个类型不能同时是整型和浮点型的实例。如果你有这样的类型,就不需要转换了。然而,这些类型类中每一个的语义含义使得单个类型很难以有意义的方式成为两者的实例。
其次,在谈论类型类时,您应该更加小心一些。它们从根本上不同于面向对象的子类型。由于概念上的差异,也存在术语上的差异。准确地使用术语有助于理解差异,并与他人进行交流。
那么,我该如何表达这个问题呢?例如“我如何将一个整数转换为浮点型的实例?我需要使用sqrt :: Floating a => a -> a函数,并将其结果与Integer值进行比较。”
发布于 2010-12-11 18:20:02
您已经得到了答案,但这可能有助于避免功能中出现类似的问题:
http://www.haskell.org/haskellwiki/Converting_numbers
作为一个背景几乎完全是动态类型语言的人,我有时也会遇到同样的问题,所以我养成了在编写Haskell函数时总是从签名开始的习惯。它确实帮助我推理出我所期望的以及我哪里错了。
https://stackoverflow.com/questions/4415303
复制相似问题