时髦的 haskell 惰性列表隐式递归

2024-03-03

在 Haskell 中,由于懒惰,您可以构建无限列表:

Prelude> let g = 4 : g
Prelude> g !! 0
4
Prelude> take 10 g
[4,4,4,4,4,4,4,4,4,4]

现在,当我尝试构建这样的列表时到底发生了什么?

Prelude> let f = f !! 10 : f
Prelude> f !! 0
Interrupted.
Prelude> take 10 f
[Interrupted.
Prelude>

The Interrupted.等待几秒钟后我按下了 CTRL+C。似乎进入了无限循环,但为什么会这样呢?


对非 Haskeller 的解释:

The :运算符是prepend:

Prelude> 4 : [1, 2, 3]
[4,1,2,3]

这行:

Prelude> let g = 4 : g

说“让g是通过前置构建的列表4进入列表g"。当您请求第一个元素时,会返回 4,因为它已经存在。当您请求第二个元素时,它会查找 4 之后的元素。该元素将是列表的第一个元素g,我们刚刚计算出 (4),所以4被返回。下一个元素是第二个元素g,我们刚刚计算过,等等......

!!只是索引到列表中,所以这意味着获取索引处的元素0 from g:

Prelude> g !! 0
4

但是当我这样做时:

Prelude> let f = f !! 10 : f

有些东西坏了,因为要计算第一个元素f你需要第 11 个元素,但它还不存在?不过,我希望有一个例外,而不是无限循环......


在这种情况下,一张图片可以讲述一千个单词。

首先,记住缺点((:)列表构造函数)有效。它由两件事组成:一个元素和对列表尾部的引用(这要么是另一个缺点,要么[]).

你应该知道,当你说[1, 2, 3],这只是一个捷径(1:(2:(3:[]))) or 1:2:3:[]。如果将每个 cons 对可视化为带有两个插槽的盒子,则此表达式如下所示:

┌───┬──┐  ┌───┬──┐  ┌───┬──┐  ┌────┐
│ 1 │ ─┼─>│ 2 │ ─┼─>│ 3 │ ─┼─>│ [] │
└───┴──┘  └───┴──┘  └───┴──┘  └────┘

One loop

当你说g = 4 : g,你并没有真正构建一个“无限”列表,你正在构建一个circular list: g被定义为一个 cons,其尾部引用简单地指向g itself:

┌──────────┐
│ ┌───┬──┐ │
└>│ 4 │ ─┼─┘
  └───┴──┘

这实际上与懒惰无关,一切都与自引用无关:例如,你可以在(热切的)Common Lisp 中使用类似的语法做同样的事情'#1=(4 . #1#)(其中#1就好像g).

无论你说g !! 0, or g !! 1000000000000, g永远不会增长:(!!)只是在原地围绕循环运行,按照您指定的次数运行,直到它耗尽自身并返回元素,4.

两个循环

当你说f = (f !! 10) : f,同样的事情发生了——除了现在,元素槽包含与4:

┌──────────┐
│ ┌───┬──┐ │
└>│ ╷ │ ─┼─┘
  └─┼─┴──┘
    │
    │ ┌───────────┐
    └>│ (f !! 10) │
      └───────────┘

至关重要的是,这个子表达式also回指f,就像尾巴一样:

 ┌──────────┐
 │ ┌───┬──┐ │
┌┴>│ ╷ │ ─┼─┘
│  └─┼─┴──┘
│    │
│    │ ┌───────────┐
│    └>│ (f !! 10) │
│      └──┼────────┘
└─────────┘

所以,当你要求f !! n, (!!)将首先绕顶部循环运行n次,然后返回该元素,就像g。然而,不是逃避循环,(f !! 10)只需重新进入,该过程就会重复进行:围绕顶部循环 10 次,然后围绕底部循环一次,然后返回。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

时髦的 haskell 惰性列表隐式递归 的相关文章

  • 为自定义镜头编写类别实例

    我一直在读这个article http www haskellforall com 2012 01 haskell for mainstream programmers 28 html用于理解镜头 我知道这不同于 爱德华 克内特 Edwar
  • 测试列表是否已排序

    在 haskell 中找到最小列表确实很容易 foldl1 min 9 5 7 3 7 4 6 10 给我3 我更换了min with lt 测试列表是否已排序 foldl1 lt 9 5 7 3 7 4 6 10 我收到此错误消息 No
  • 结构上强制的自由替代,没有左派分配性

    有一个不错的免费替代品 http hackage haskell org package free 4 12 4 docs Control Alternative Free html在伟大的free包 它将函子提升到左分配替代方案 也就是说
  • 镜头中的观看和使用有什么区别?

    有什么区别 view MonadReader s m gt Getting a s a gt m a and use MonadState s m gt Getting a s a gt m a in 控制镜头吸气剂 https hacka
  • Control.Arrow 与 Data.Tuple.Extra

    我经常使用以下功能Data Tuple Extra图书馆 first second and both 有等效的 函数Control Arrow 其实我更喜欢Data Tuple Extra因为我完全迷失了文档Control Arrow 使用
  • Haskell:如何创建将函数应用于元组项的最通用函数

    这是一个个人练习 旨在更好地理解 Haskell 类型系统的局限性 我想创建最通用的函数 将某些函数应用于 2 条目元组中的每个条目 例如 applyToTuple fn a b fn a fn b 我试图让这个函数在以下每种情况下都起作用
  • 表达式“ap zip tail”如何工作

    我想知道怎么写f x zip x tail x 点免费 所以我使用了pointfree程序 结果是f ap zip tail ap作为 Control Monad 的函数 我不明白点自由定义是如何工作的 如果我能从类型的角度去理解的话 希望
  • Haskell 中的常量变量声明

    要声明常量变量 我可以在 Ruby 中执行以下操作 class COLOR RED 10 BLUE 20 GREEM 30 end COLOR RED回报10 COLOR BLUE回报20 等等 我如何在 Haskell 中实现这一点 我想
  • 'lens' 的阴谋集团依赖性解析失败

    我刚刚做了一个阴谋更新并尝试从 hackage 安装 lens 这给了我以下错误 cabal install j lens Resolving dependencies Configuring dlist 0 7 0 1
  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 如何找到仅是 2、3 和 5 的幂的倍数的所有数字的列表? [复制]

    这个问题在这里已经有答案了 I am trying to generate a list of all multiples which can be represented by the form where a b and c are w
  • 我应该使用镜头中的什么来按索引构建只读吸气剂?

    我有一个内部细节被隐藏的类型 我想提供某种镜头 可以在特定索引处读取所述类型的元素 但是not修改它们 一个Ixed我的类型的实例似乎没有做我想要的事情 因为它明确允许修改 尽管不允许插入或删除 如果我想允许只读索引 我不确定我使用什么 如
  • 处理许多不相关的类型时避免样板

    我正在编写处理以下值的代码语言 扩展 注释 语法 http hackage haskell org packages archive haskell src exts 1 1 4 doc html Language Haskell Exts
  • 对元组列表进行排序的函数 - Haskell

    抱歉 这个简单的问题只是我对 haskell 非常陌生 我正在尝试编写一个函数 order 它将对另一个函数 Frequency 生成的元组列表进行排序 频率计算列表中不同元素的数量 a给出一个这样的结果 比如 gt 频率 aabbbccc
  • 带有查询参数的渲染 url

    无法找到简单问题的解决方案 答案应该是显而易见的 如何在 hamlet 模板中使用查询参数渲染 url I e ItemsR 将生成http localhost 3000 items我如何生成类似的东西http localhost 3000
  • 在 Haskell 命令行应用程序中提示输入密码

    以下 Haskell 程序提示用户在终端中输入密码 如果输入正确则继续 main do putStrLn Password password lt getLine case hash password member database of
  • 有没有办法在 Emacs 中使用 Djinn 自动生成 Haskell 代码?

    标题几乎说明了一切 我正在寻找这样的东西 f Int gt Bool gt Int f body Djinn 可以使用定理证明来通过证明该类型存在来生成此类函数的代码 我想知道 是否有现有的方法可以从 Emacs 中获取此功能 因此 我不需
  • 嵌套在其他 monad 中的 IO 操作未执行

    我有一个 foobar IO ParseResult String String ParseResult 是一个在这里定义的 monad https hackage haskell org package haskell src exts
  • 有什么方法可以在 do / while / let 块中打印出变量的类型吗?

    有没有办法打印出嵌套变量的推断类型ghci 考虑代码 let f g where g x Int x 那么 最好查询一下类型g e g t f g会打印出Int gt Int 您可以通过给出适当的错误类型注释并检查错误消息来诱骗此信息 Ma
  • 管道中缺少 ResourceT 实例

    我在尝试使用时遇到奇怪的错误ResourceT http hackage haskell org package conduit 1 0 9 1 docs Data Conduit html t 3aResourceT来自管道 1 0 9

随机推荐