我是Haskell的新手,我正在尝试一下:
isPrime :: Integer->Bool
isPrime x = ([] == [y | y<-[2..floor (sqrt x)], mod x y == 0])
我有几个问题。
(Floating Integer, RealFrac Integer)
的实例需要isPrime
的实例?对不起我的英语。
答案 0 :(得分:17)
1)问题是sqrt
的类型为(Floating a) => a -> a
,但您尝试使用Integer作为参数。因此,您必须先将Integer转换为浮点数,例如写sqrt (fromIntegral x)
2)我认为没有理由为什么==不应该是懒惰的,但是为了测试一个空集合你可以使用null
函数(这绝对是懒惰的,因为它适用于无限列表):< / p>
isPrime :: Integer->Bool
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0]
但是为了获得更加惯用的解决方案,将问题分解为更小的子问题。首先,我们需要y * y&lt; = x:
的所有元素y的列表takeWhile (\y -> y*y <= x) [2..]
然后我们只需要划分x:
的元素filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..])
然后我们需要检查该列表是否为空:
isPrime x = null (filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..]))
如果这看起来像你好,请用$
替换一些parensisPrime x = null $ filter (\y -> x `mod` y == 0) $ takeWhile (\y -> y*y <= x) [2..]
为了更加清晰,你可以“外包”lambdas:
isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
通过将null $ filter替换为$ any:
,可以使其几乎“人类可读”isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where
divisible y = x `mod`y == 0
notTooBig y = y*y <= x
答案 1 :(得分:7)
因为sqrt
的类型为Floating a => a -> a
。这意味着输入必须是Floating
类型,输出将是相同的类型。换句话说,x
必须是Floating
类型。但是,您声明x
属于Integer
类型,而不是Floating
类型。另外floor
需要RealFrac
类型,因此x
也需要这样。
错误消息表明您通过将Integer
设为Floating
类型(通过定义实例Floating Integer
(以及RealFrac
的相同内容)来解决此问题。
当然,在这种情况下,这不是正确的方法。相反,您应该使用fromIntegral
将x
转换为Real
(Floating
和RealFrac
的实例),然后将其转换为sqrt
}。
是。只要==
看到右操作数至少有一个元素,它就知道它不等于[]
,因此返回False
。
话虽如此,null
是一种更为惯用的方式来检查列表是否为空[] ==
。
答案 2 :(得分:1)
关于第二点,它会停止,例如:
[] == [x | x <- [1..]]
返回False
答案 3 :(得分:1)
Landei的解决方案很棒,但是,如果你想要一个更高效的¹实现(感谢BMeph):
-- list of all primes
primes :: [Integer]
primes = sieve (2 : 3 : possible [1..]) where
sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]
possible (x:xs) = 6*x-1 : 6*x+1 : possible xs
isPrime :: Integer -> Bool
isPrime n = shortCircuit || (not $ any divisible $ takeWhile inRangeOf primes) where
shortCircuit = elem n [2,3] || (n < 25 && ((n-1) `mod` 6 == 0 || (n+1) `mod` 6 == 0))
divisible y = n `mod` y == 0
inRangeOf y = y * y <= n
'效率'来自使用常数素数。它以两种方式改进了搜索:
答案 4 :(得分:-2)
isPrime 32
然后它将懒惰地计算表达式。PS你的isPrime实现不是最好的实现!