haskell - 这是我懒惰的分区吗?

2 haskell lazy-evaluation

例如

partitions [1,2,3] =
  [([],[1,2,3])
  ,([1],[2,3])
  ,([1,2],[3])
  ,([1,2,3],[])]
Run Code Online (Sandbox Code Playgroud)
partitions :: [a] -> [([a], [a])]
partitions (x:xs) = ([], x:xs):[(x:ys, rs) | (ys, rs) <- partitions xs]
Run Code Online (Sandbox Code Playgroud)

我想知道它是懒惰的解决方案.例如partitions [1..]是无限的.另外, take 5 $ partitions [1..]也是无限的.鉴于此函数的结果是无限的,我认为这很明显.但是,如果我正确地理解懒惰,我不确定它是否是懒惰的.

chi*_*chi 6

有不同程度的懒惰.

有人可能会说你的函数是严格的,因为partitions undefined触发了一个例外,但那太迂腐了.

可能是"懒惰"你实际上意味着"它只会在访问输入的一部分后产生输出的一部分".然后出现几度懒惰,这取决于输出的每个部分需要多少输入.

在您的情况下,函数的形状如下:

foo [] = (some constant value)
foo (x:xs) = C expression1 ... expressionN
Run Code Online (Sandbox Code Playgroud)

where C值是一个值构造函数.更确切地说,C = (:)N=2.由于Haskell构造函数是惰性的(除非涉及爆炸注释),因此结果foo (x:xs)将始终为非底部:在输入列表中使用元素足以生成输出列表的元素.

您可能会对partitions [1..]作为无限列表对的输出感到困惑,(xs, ys)其中每个对ys都是无限列表.这使得懒惰的概念变得更加复杂,因为您现在可能想知道,例如"我输入了多少输入来获取第100对输出,然后访问其第二个组件的第500个元素?".这些问题是完全合法的,一般来说很难回答.

但是,您的代码永远不会要求完整的输入列表输出有限的输出部分.这使它"懒惰".


为了完整起见,让我展示一个懒惰的功能:

partitions (x:xs) = case partitions xs of
   []     -> expression0
   (y:ys) -> expression1 : expression2 
Run Code Online (Sandbox Code Playgroud)

在上面,在产生输出列表的头部之前需要递归调用的结果.这将在生成输出的任何部分之前要求整个输入.

  • @Sibi它将取决于所讨论功能的细节.重要的是*生产力*:在有限的"时间"内创建有限部分的输出.这显然意味着它只会检查其输入的有限部分.`partitions`在生成它的第一个元素之前检查它的整个输入列表,所以如果那个列表是无限的......那就是说它在输入列表的主干中是严格的意思,我收集. (2认同)