Haskell - 导致列表理解立即终止

时间:2018-06-10 08:31:02

标签: list haskell

我正在尝试编写一个能够有效地告诉我何时的函数 列表中的项目可以被一个范围内的所有项目整除或不整除。问题是,我不知道在遇到错误时立即停止列表理解。

allDivisByRng n start stop =
  [n `mod` x == 0 | x <- [start, start+1 .. stop]]

我已经尝试takeWhile但是无法做到我想做的事情。请指教。

allDivisByRng n start stop =
  takeWhile( == True )     [ n  `mod`  x == 0 | x <- [start, start+1.. stop] ]

当我运行allDivisByRng 10 2 4时,我会得到一个真实的列表

其他一些示例运行

*Main> allDivisByRng 12 2 10
[True,True,True]
*Main> allDivisByRng 12 2 150
[True,True,True]
-- I want this to return false
*Main> allDivisByRng 2520 2 10
[True,True,True,True,True,True,True,True,True]
-- I want this to return True

我也尝试过搜索False

allDivisByRng n start stop =
   takeWhile( == False )     [ n  `mod`  x == 0 | x <- [start, start+1.. stop] ]

*Main> allDivisByRng 10 2 3
[]
-- want false to be returned
*Main> allDivisByRng 10 2 10
[]
-- want false to be returned
*Main> allDivisByRng 2520 2 10
[]
-- want true to be returned
*Main> allDivisByRng 12 2 10
[]
-- want false to be returned 

2 个答案:

答案 0 :(得分:5)

函数all

all :: Foldable t => (a -> Bool) -> t a -> Bool

允许您检查可折叠结构的所有元素是否满足特定条件。在你的情况下,

allDivisByRng n start stop = all ((== 0) . (mod n)) [start..stop]

答案 1 :(得分:2)

不需要&#34;停止列表理解&#34;在哈斯克尔。默认情况下,评估为lazy。这意味着在实际需要之前,值并未真正计算出来。

这使我们可以使用无限的数据结构:

take 10 [1..]
--> [1,2,3,4,5,6,7,8,9,10]

或者结构中包含无效值的结构:

take 1 ["It works!", error "Exception thrown"]
--> "It works!"

所以我们只需要将列表处理成一个函数,将布尔列表减少到一个bool。

Hoogle是一个很棒的小工具,用于搜索与给定类型签名匹配的函数。我建议你熟悉它,因为通常情况下,你并不能找到你正在寻找的东西。

在这种情况下,搜索[Bool] -> Bool(将布尔值列表减少为单个布尔值的函数)为我们提供了Prelude中定义的以下函数(无需导入):

and :: Foldable t => t Bool -> Bool

看看你是否可以应用它来获得你想要的东西!

恰好有另一个函数对我们想要的东西有点闭合:测试列表中的所有元素是否满足谓词。有了这个&#34; all&#34;功能,我们可以用非常清晰的方式重写你的功能(imo):

allDivisByRng n start stop =
    all (n `isDividedBy`) [start .. stop]
    where
        n `isDividedBy` x  =  n `mod` x == 0