Haskell 中的循环列表和无限列表有什么区别?

2024-01-01

参考@dfeuer对此问题的回答:在 Haskell 中构造循环列表的最便宜的方法 https://stackoverflow.com/questions/25374736/least-expensive-way-to-construct-cyclic-list-in-haskell,它说使用循环列表会“击败”垃圾收集器,因为它必须保留您从分配的循环列表中消耗的所有内容,直到您删除对列表中任何 cons 单元的引用为止。

显然,在 Haskell 中,循环列表和无限列表是两个不同的东西。这个博客(https://unspecified.wordpress.com/2010/03/30/a-doubly-linked-list-in-haskell/ https://unspecified.wordpress.com/2010/03/30/a-doubly-linked-list-in-haskell/)说如果你实施cycle如下:

cycle xs = xs ++ cycle xs

它是一个无限列表,而不是循环列表。要使其循环,您必须像这样实现它(如 Prelude 源代码中所示):

cycle xs = xs' where xs' = xs ++ xs'

这两种实现方式到底有什么区别?为什么如果您在循环列表中的某处保留一个 cons 单元,那么垃圾收集器也必须在分配之前保留所有内容?


差异完全在于内存表示。从语言语义的角度来看,它们是无法区分的——你无法编写一个函数来区分它们,所以你的两个版本cycle被视为同一函数的两种实现(它们是参数到结果的完全相同的映射)。事实上,我不知道语言定义是否保证其中一个是循环的,另一个是无限的。

但无论如何,让我们展示一下 ASCII 艺术。循环列表:

   +----+----+                 +----+----+
   | x0 |   ----->   ...   --->| xn |    |
   +----+----+                 +----+-|--+
     ^                                |
     |                                |
     +--------------------------------+

无限列表:

   +----+----+
   | x0 |   ----->  thunk that produces infinite list
   +----+----+

循环列表的问题是,列表中的每个 cons 单元格都有一条通向所有其他单元格的路径和它本身。这意味着从垃圾收集器的角度来看,如果其中一个 cons cell 是可访问的,那么所有 cons cell 都是可访问的。另一方面,在普通的无限列表中,没有任何循环,因此从给定的 cons 单元只能到达其后继单元。

请注意,无限列表表示比循环表示更强大,因为循环表示仅适用于在一定数量的元素之后重复的列表。例如,所有素数的列表可以表示为无限列表,但不能表示为循环列表。

另请注意,这种区别可以概括为两种不同的实现方式fix功能:

fix, fix' :: (a -> a) -> a
fix  f = let result = f result in result
fix' f = f (fix' f)

-- Circular version of cycle:
cycle  xs = fix (xs++)

-- Infinite list version of cycle:
cycle' xs = fix' (xs++)

GHC 库适合我fix定义。 GHC 编译代码的方式意味着创建的 thunk 是为result用来both作为应用的结果和论证f。即,thunk 在被迫时将调用目标代码f以 thunk 本身作为参数,并用结果替换 thunk 的内容。

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

Haskell 中的循环列表和无限列表有什么区别? 的相关文章

  • 我们不应该使用单子绑定来使用循环写下 mfix 的情况

    我一直在尝试写mfix向下使用Control Arrow loop https hackage haskell org package base 4 14 0 0 docs src Control Arrow html loop 我想出了不
  • 为什么 GeneralizedNewtypeDeriving 没有安全的 Haskell?

    来自 GHC 手册 第安全语言 http www haskell org ghc docs 7 6 2 html users guide safe haskell html safe language 模块边界控制 使用安全语言编译的 Ha
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • 如何获取常量内存中的统计数据

    我有一个函数 它会创建一些随机的数值结果 我知道 结果将是 a 小 a b 约 50 范围内的整数a b 我想创建一个执行上述函数 1000000 次的函数 并计算每个结果出现的频率 该函数使用随机生成器来生成结果 问题是 我不知道如何在常
  • 将 Either 列表转换为其中包含列表的 Either 列表

    我是 Haskell 的初学者 我正在编写一些使用 Haskell 的代码Either https hackage haskell org package base 4 9 0 0 docs Data Either html用于错误处理 E
  • 如何将只缓存某些内容的字段添加到ADT?

    我经常需要向 ADT 添加字段 仅记住一些冗余信息 但我还没有完全弄清楚如何又好又高效地做到这一点 说明问题的最好方法是举个例子 假设我们正在使用无类型 lambda 项 type VSym String data Lambda Var V
  • 处理许多不相关的类型时避免样板

    我正在编写处理以下值的代码语言 扩展 注释 语法 http hackage haskell org packages archive haskell src exts 1 1 4 doc html Language Haskell Exts
  • Haskell 测量函数性能

    在 Haskell 中 我如何 简单地 测量函数的性能 例如 运行需要多长时间 或者需要多少内存 我知道分析 但是 是否有一种更简单的方法不需要我对代码进行太多更改 测量运行需要多长时间以及需要多少内存是两个独立的问题 即 基准测试和分析
  • 如何组合过滤条件

    过滤器类函数接受一个条件 a gt Bool 并在过滤时应用它 当您有多个条件时 使用过滤器的最佳方法是什么 使用了应用函数 liftA2 而不是 liftM2 因为出于某种原因我不明白 liftM2 在纯代码中如何工作 liftM2 组合
  • 有什么方法可以在 do / while / let 块中打印出变量的类型吗?

    有没有办法打印出嵌套变量的推断类型ghci 考虑代码 let f g where g x Int x 那么 最好查询一下类型g e g t f g会打印出Int gt Int 您可以通过给出适当的错误类型注释并检查错误消息来诱骗此信息 Ma
  • 如何避免编写这种类型的 Haskell 样板代码

    我经常遇到这种情况 这很烦人 假设我有一个 sum 类型 它可以保存一个实例x或一堆其他无关的事情x data Foo x X x Y Int Z String other constructors not involving x 要声明
  • 如何使用 Haskell 提交 html 表单

    我知道如何使用http 管道 http hackage haskell org package http conduit 2 1 0包的 simplehttp 从 URL 检索页面 现在如果那样的话怎么办 网页有一个输入文本字段和一个提交按
  • Haskell 类型定义,=> 等

    我正在使用 Learn You a Haskell 来学习 Haskell 第 54 页上有一个 像这样执行 take Num i Ord i gt i gt a gt a take n n lt 0 take take n x xs x
  • 为什么以下内容会并行运行而不是顺序运行?

    给定以下函数evalPair parPair and deepSeq分别 evalPair Strategy a gt Strategy b gt Strategy a b evalPair sa sb a b do a lt sa a b
  • 没有由文字“1”产生的 Num String 实例

    main do putStrLn myLast 1 2 3 4 myLast a gt a myLast x x myLast xs myLast xs 当我尝试运行此代码时 我收到此消息 没有由文字 1 产生的 Num String 实例
  • 如何处理或避免BlockedIndefinitelyOnSTM异常?

    我花了很多时间来解决我正在处理的应用程序中遇到的问题 该应用程序是一个 Web 应用程序 使用 scotty 公开 REST 端点 它使用一个TVar保持其更新的状态STM a由前端层触发的动作 由于该应用程序基于事件溯源原则 因此业务层生
  • Haskell 中的多态函数作为参数

    我有一个带有两个构造函数的 ADT 一个包裹着一个Double和一个包裹着Integer 我想创建一个函数 它采用一元函数Numtypeclass 并返回一个函数 该函数将该一元函数应用于我的 ADT 的内容 我试过这个 data X Y
  • 是否有适用于 Haskell 或 Scala 等函数式语言的 LL 解析器生成器?

    我注意到明显缺乏用函数式语言创建解析器的 LL 解析器 我一直在寻找但没有成功的理想发现是为 ANTLR 风格的 LL 语法生成 Haskell 解析器 语法的模小数重新格式化 并且令我惊讶的是 每个最后一个解析器生成器都具有函数我发现的语
  • Haskell 中的所有图形和 Web 库是如何实现的?

    我才开始学习Haskell 我读到它是一种纯函数式语言 其中的所有内容都是不可变的 因此 输入输出 写入和读取数据库之类的事情会导致状态的可变性 我知道 Haskell 中有一种叫做 monad 的东西 它允许在 Haskell 中使用命令
  • Haskell:从后面访问列表

    今天我开始学习Haskell 我对函数式语言有点陌生 而且我非常喜欢 Haskell 然而 我有一个关于它的设计的问题困扰着我 从我到目前为止的理解来看 访问列表后面的元素似乎比访问前面的元素要复杂得多 类似于xs x where xs a

随机推荐