关于无限搜索功能:
已经有一个函数可以在列表中搜索值 - elem
。
如果您假设无限列表已排序,我们可以编写一个适用于此类列表的 elem 版本。这可以通过首先拒绝任何小于搜索值的元素来轻松完成。那么第一个未被拒绝的值必须等于或大于搜索元素。如果相等 - 返回真,否则返回假
infiniteElem1 :: (Ord a) => a -> [a] -> Bool
infiniteElem1 x list = (== x) $ head $ dropWhile (< x) list
示例用法:
> infiniteElem1 10 [1..]
True
> infiniteElem1 10 [1,3..]
False
但是有一个问题infiniteElem1
:如果在有限列表上使用,如果找不到元素,它可能会抛出异常:
> infiniteElem1 100 [1,2,3]
*** Exception: Prelude.head: empty list
head
这是最好避免使用该功能的原因。一个更好的解决方案是:
infiniteElem :: (Ord a) => a -> [a] -> Bool
infiniteElem x list = case dropWhile (< x) list of
[] -> False
(v:_) -> v == x
现在它也适用于有限排序列表:
> infiniteElem 100 [1,2,3]
False
有了这个,你的问题就变得微不足道了:
let isSquare n = n `infiniteElem` [ x * x | x <- [1..]]