【问题标题】:Using foldr on a list of infinite lists在无限列表上使用 foldr
【发布时间】:2021-12-14 15:32:32
【问题描述】:

我正在尝试在 Haskell 中编写一个函数,它执行以下操作: 您输入一个整数列表,对于这些整数,使用 map,有一个函数应用于它们,返回这些整数的无限列表。然后,我想使用 union 将 foldr 应用于列表列表,以便结果将是列表中这些列表的并集。

现在的问题是,当我例如取 10 'function' [1,2] 时,它会首先计算 1 的无限列表,因为它是一个无限列表,所以它永远不会为 2 这样做。所以它只返回输入列表中第一个元素的这个无限列表的前 10 个元素,并对其应用联合,这就是同一个列表。

我的问题是:有没有办法同时为输入列表中的所有元素创建无限列表,这样当我以 10 'function' [1,2] 为例时,它会返回1 和 2 的无限列表并集的前 10 个元素。 (不知道输入列表的元素个数)

这是我的代码,为了更清楚:

pow :: Integer -> [Integer]
pow n = map (^n) [1, 2..]

function :: [Integer] -> [Integer]
function xs = foldr union [] (map pow xs)

【问题讨论】:

    标签: list haskell functional-programming fold


    【解决方案1】:

    如果您打算对输入和输出列表进行排序,请查看data-ordlist。如果您只想要所有元素但不关心顺序,请尝试concat . transpose。

    【讨论】:

      【解决方案2】:

      union 函数适用于任意列表并删除重复项,因此它必须首先完全评估其参数之一,然后才能继续处理另一个参数。

      我认为您想明确介绍您的列表已排序的假设,然后您可以编写一个有效的函数来合并(如合并排序中的合并)输入列表并计算联合,而无需评估其中之一在另一个之前列出。

      我不知道库中是否存在这样的合并函数,但你可以很容易地自己定义它:

      -- | Computes the union of two sorted lists
      merge :: Ord a => [a] -> [a] -> [a]
      merge [] ys = ys
      merge xs [] = xs
      merge (x:xs) (y:ys)
        | x <= y    = x : merge (dropWhile (== x) xs) (dropWhile (== x) (y:ys))
        | otherwise = y : merge (x:xs) (dropWhile (== y) ys)
      

      然后,您使用这个新的 merge 函数的原始折叠应该可以正常运行:

      ghci> pow n = map (^n) [1..]
      ghci> function xs = foldr merge [] (map pow xs)
      ghci> take 10 (function [2,3])
      [1,4,8,9,16,25,27,36,49,64]
      

      【讨论】:

      • 啊,比我想象的要容易。谢谢你的快速反应!它现在似乎可以工作了!
      猜你喜欢
      • 1970-01-01
      • 2015-08-21
      • 2023-04-09
      • 2015-12-24
      • 1970-01-01
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 2015-01-10
      相关资源
      最近更新 更多