【问题标题】:How does one signify an infinite list to be ascending for elem checks?对于 elem 检查,如何表示要升序的无限列表?
【发布时间】:2016-06-04 01:24:51
【问题描述】:

我有一个无限的素数列表,由以下列表理解初始化:

primes = [x | x <- [2..], 0 `notElem` map (x `mod`) [2..(x `quot` 2)]]

这让我可以像17 `elem` primes 这样进行检查,以确认 17 是素数。但是,当我检查列表中是否有非素数时,程序不会停止计算。我假设这是因为它没有意识到如果在大于该数字的素数之前无法在列表中找到该数字,则无法在列表中的任何位置找到它。因此,Haskell 中是否有任何方式向编译器表明一个列表只包含升序数字,以便elem 检查在到达列表中大于其第一个参数的数字时知道停止并返回 false?

【问题讨论】:

    标签: list haskell primes lazy-evaluation infinite


    【解决方案1】:

    一种可能性是使用dropWhile

    isPrime n = (head $ dropWhile (< n) primes) == n
    

    【讨论】:

    【解决方案2】:

    当然。您可以定义自己的OrderedList newtype,包装无限列表,定义以OrderedList 为参数的更高效的搜索函数。

    newtype OrderedList a = OL [a]
    member a (OL as) = case dropWhile (<a) as of
      []    -> False
      (x:_) -> a == x
    

    你不能覆盖elem的行为,即使它是Foldable的类方法,因为elem的定义只要求底层元素类型为Eqable,即:

    member :: (Ord a, Eq a) => a -> OrderedList a -> Bool
    elem :: (Eq a, Foldable t) => a -> t a -> Bool
    

    您可以通过以下代码进行验证:

    instance Foldable OrderedList where
      foldMap f (OL as) = foldMap f as
      elem = member -- error: Could not deduce `Ord a` arising from a use of `member`
    

    请注意:当您的列表不是无限的时,您最好考虑使用树状结构(例如 IntSet),它们将搜索操作的复杂度从 O(n) 优化到 O(log(n ))。

    【讨论】:

    • 您能否让member 1 (OL [2..10]) 像预期的那样返回False?也可能是member 1 (OL [])。否则,它确实需要一个无限列表。
    • 这个答案的本质是“你不能教elem关于排序;搜索假定的排序列表是一个不同的操作,所以做一个不同的函数”。 newtype 包装器并不是真正直接相关的(尽管它是对后续问题“我怎样才能避免不小心将member 应用于可能未排序的列表”的一个很好的答案)。
    • @Ben +1。我更要强调的是,“,你不能elem”新技巧;你必须为此定义一个新函数。
    【解决方案3】:

    可以将其编码为折叠:

    memberOrd :: (Eq a, Ord a) => a -> [a] -> Bool
    memberOrd x = foldr (\y b -> y==x || y<x && b) False
    

    || 的懒惰使其也适用于无限列表。

    (显然,我们必须假设列表不包含无限多的元素&lt; x。我们无法突然解决无法确定的问题... ;-))

    Will Ness 下面提出了以下变体,它执行的比较较少:

    memberOrd x = foldr (\y b -> y<x && b || y==x) False
    

    【讨论】:

      猜你喜欢
      • 2011-08-22
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多