我有以下两个功能:
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 我没有看到任何错误消息。
最佳答案
问题在于primes
是一个整数列表(由于使用了mod
),但是sqrt
对浮点数进行运算。如果您执行x < (ceiling . sqrt . fromIntegral) number
,则可以正常工作。 fromIntegral
只是将整数转换为任何其他数字类型:
fromIntegral :: (Integral a, Num b) => a -> b
在这种情况下,由于您没有指定要转换为的任何特定浮点类型,因此默认情况下将使用Double值来计算平方根。您可以通过将
fromIntegral
更改为(fromIntegral :: Integer -> Float)
之类来指定其他类型。您没有在GHCi中看到此错误的原因是您的条件很好。它只适用于与您在此使用的类型不同的类型。仅仅验证一段代码是正确的,还不够。为了使其通过类型检查器,它在上下文中也必须有意义。
您可能需要考虑使用integer square root algorithm以获得准确性。