【问题标题】:Check if item is in infinite List检查项目是否在无限列表中
【发布时间】:2017-11-02 07:44:28
【问题描述】:

我有一个相当基本的问题,关于与无限列表进行比较。问题类似这样:

25 `elem` [x^2 | x <- [1..]]

显然这是true。 但是,如何处理不在列表中的值,例如

26 `elem` [x^2 | x <- [1..]]

因为它是一个无限列表,Haskell 对此没有答案,虽然看起来有点明显,一旦我们超过 6^2,我们就不能再达到 26,所以我想停在那里。

现在我可以像这样限制 x:

[x^2 | x <- [1..6]]

简单。

但是我在这样的例子中做了什么:

[prod | k <- [1..], let prod = product [1..k]]

我想检查我的号码是否在该列表中?或者有什么替代方法可以得到这个计算的结果?

【问题讨论】:

  • 您知道您的列表将始终按递增顺序排列吗?
  • 通常你无法知道一个列表是否是无限的,因为这会解决Halting问题。但是,在这种情况下,您可以知道这一点,因为列表严格增加。
  • 此外,[prod | k &lt;- [1..], let prod = product [1..k]] 等同于 [product [1..k] | k &lt;- [1..]]
  • …等价于scanl1 (*) [1..]!
  • 是的,列表将始终按升序排列。而且实际的计算更复杂(乘素数)。

标签: haskell functional-programming


【解决方案1】:

data-ordlist 包有许多用于处理排序列表的实用函数,包括member

Data.List.Ordered> 25 `member` [n^2 | n <- [1..]]
True
Data.List.Ordered> 26 `member` [n^2 | n <- [1..]]
False
Data.List.Ordered> 24 `member` [product [1..k] | k <- [1..]]
True
Data.List.Ordered> 25 `member` [product [1..k] | k <- [1..]]
False

【讨论】:

    【解决方案2】:

    如果您的列表是按升序排列的,您可以find 至少是您要查找的元素,并分别检查它是否相同:

    > let elemIncreasing x l = find (>= x) l == Just x
    > let factorials = scanl1 (*) [1..]
    > 120 `elemIncreasing` factorials
    True
    > 121 `elemIncreasing` factorials
    False
    

    【讨论】:

      【解决方案3】:

      假设我们有一些订单

      sortedElem _ _ [] = False
      sortedElem (<) y (x:xs) | y == x = True
                              | x < y  = False
                              | True   = sortedElem (<) y xs
      

      您可以定义特殊情况,例如

      elemIncreasing = sortedElem (<)
      elemDecreasing = sortedElem (>)
      

      我正在使用手机,所以我没有对此进行测试。它原则上应该可以工作,但编译器可能有一些问题。我确信它们可以修复。

      【讨论】:

      • 我不会在你的类型签名中使用(&lt;),因为它似乎没有除了表明干草堆是上升还是下降。改为考虑data ListOrder = Asc | DescsortedElem :: (Eq a, Ord a) =&gt; ListOrder -&gt; a -&gt; [a]
      • 此实现不需要元素实现Ord 或者实际上它们按此顺序排序。这两个示例适用于实现 Ord 的事物列表,但 sortedElem 函数可用于例如按例如排序的复数列表增加幅度,或按最大因子或任何其他奇怪顺序排序的数字列表。
      • 你确定吗?如果是这种情况,我不知道怎么做,因为你使用 x &lt; y 作为守卫,它在 Ord a 上运行。
      • @AdamSmith 这不需要Ord,因为&lt; 是参数的名称,隐藏在Ord 类型类中的那个。
      • &lt; 对您传递的任何内容进行操作。它在词法上被绑定为函数参数。以下是等效的:satisfies (&lt;) a b = a &lt; bsatisfies f a b = f a b
      猜你喜欢
      • 1970-01-01
      • 2011-09-02
      • 2017-12-21
      • 2021-06-25
      • 2012-06-30
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多