可以在infinte maybes上排序吗?

时间:2018-01-10 23:15:15

标签: haskell fold strictness

换句话说,可以将以下内容优化为Just [1..]吗?

> sequence (map Just [1..])
*** Exception: stack overflow

data61/fp-course中还有一个更具体的示例,如果存在Empty值,则会提前终止。

seqOptional ::
  List (Optional a)
  -> Optional (List a)
seqOptional =
    foldRight f (Full Nil)
      where
          f Empty _ = Empty
          f _ Empty = Empty
          f (Full a) (Full as) = Full (a :. as)

为什么改变前两个模式的顺序使函数循环永远,就好像Empty不能匹配一样?我隐约明白,这样的定义会使f在无限列表中变得严格,但我不知道究竟是什么导致了这一点。

或者这些无关的问题是什么?

附带问题:堆栈耗尽而不是堆是否重要?

2 个答案:

答案 0 :(得分:3)

即使可以,也不应该。与@ user2407038的评论一样,根据Haskell的denotational semanticssequence (map Just [1..])表示与Just [1..]不同的值。

Haskell函数是连续,这是精确推理无限数据结构的关键工具。为了说明连续性意味着什么,假设我们有一个越来越明确的无限值序列,例如:

⟂
1:⟂
1:2:⟂
1:2:3:⟂

现在,为每个人应用一个函数,让我们说tail

tail ⟂             = ⟂
tail (1:⟂)         = ⟂
tail (1:2:⟂)       = 2:⟂
tail (1:2:3:⟂)     = 2:3:⟂
     ⋮                 ⋮
tail [1..]         = [2..]

函数连续的意思是,如果将函数应用于参数序列的 limit ,则得到序列的 limit 结果,如最后一行所示。

现在对部分定义的列表中的sequence进行了一些观察:

-- a ⟂ after a bunch of Justs makes the result ⟂
sequence (Just 1 : Just 2 : ⟂) = ⟂
-- a Nothing anywhere before the ⟂ ignores the ⟂ (early termination)
sequence (Just 1 : Nothing : ⟂) = Nothing

我们只需要第一次观察。我们现在可以问你的问题:

sequence (map Just ⟂)       = sequence ⟂                     = ⟂
sequence (map Just (1:⟂))   = sequence (Just 1 : ⟂)          = ⟂
sequence (map Just (1:2:⟂)) = sequence (Just 1 : Just 2 : ⟂) = ⟂
          ⋮                                   ⋮                 ⋮
sequence (map Just [1..])                                    = ⟂

通过连续性,sequence (map Just [1..]) = ⟂。如果你"优化"它给出了不同的答案,优化是不正确的。

答案 1 :(得分:0)

我无法回答你的第二个问题,但可以回答你的第一个问题。

理论上,编译器可以检测和优化这样的情况,但由于停机问题,它无法检测此模式的每个实例。它可以做的最好的是一堆临时启发式,我认为如果程序的终止取决于是否触发了特定的重写规则,那将更加令人困惑。