为什么 GHC 使修复变得如此令人困惑?

2024-03-06

查看 GHC 源代码我可以看到定义fix is:

fix :: (a -> a) -> a
fix f = let x = f x in x

在一个例子中fix像这样使用:

fix (\f x -> let x' = x+1 in x:f x')

这基本上会产生一系列加一到无穷大的数字。为了让这件事发生fix必须将它接收到的函数柯里化回该函数作为它的第一个参数。我不清楚如何定义fix上面列出的可以做到这一点。

这个定义就是我如何理解的fix works:

fix :: (a -> a) -> a
fix f = f (fix f)

所以现在我有两个问题:

  1. 如何x曾经意味着fix x在第一个定义中?
  2. 使用第一个定义比使用第二个定义有什么优势吗?

通过应用等式推理,很容易看出这个定义是如何运作的。

fix :: (a -> a) -> a
fix f = let x = f x in x

什么会x当我们尝试评估时评估fix f?它定义为f x, so fix f = f x。但什么是x这里?它是f x,就像以前一样。所以你得到fix f = f x = f (f x)。以这种方式推理,你会得到无限的应用链f: fix f = f (f (f (f ...))).

现在,替换(\f x -> let x' = x+1 in x:f x') for f you get

fix (\f x -> let x' = x+1 in x:f x')
    = (\f x -> let x' = x+1 in x:f x') (f ...)
    = (\x -> let x' = x+1 in x:((f ...) x'))
    = (\x -> x:((f ...) x + 1))
    = (\x -> x:((\x -> let x' = x+1 in x:(f ...) x') x + 1))
    = (\x -> x:((\x -> x:(f ...) x + 1) x + 1))
    = (\x -> x:(x + 1):((f ...) x + 1))
    = ...

Edit:关于你的第二个问题,@is7s在评论中指出,第一个定义更可取,因为它更有效。

为了找出原因,让我们看看核心fix1 (:1) !! 10^8:

a_r1Ko :: Type.Integer    
a_r1Ko = __integer 1

main_x :: [Type.Integer]   
main_x =
  : @ Type.Integer a_r1Ko main_x

main3 :: Type.Integer
main3 =
  !!_sub @ Type.Integer main_x 100000000

正如你所看到的,转换后fix1 (1:)本质上变成了main_x = 1 : main_x。请注意这个定义是如何引用它本身的——这就是“喜结良缘”的意思。这种自引用在运行时表示为简单的指针间接:

现在让我们看看fix2 (1:) !! 100000000:

main6 :: Type.Integer
main6 = __integer 1

main5
  :: [Type.Integer] -> [Type.Integer]
main5 = : @ Type.Integer main6

main4 :: [Type.Integer]
main4 = fix2 @ [Type.Integer] main5

main3 :: Type.Integer
main3 =
  !!_sub @ Type.Integer main4 100000000

这里的fix2应用程序实际上被保留:

结果是第二个程序需要为列表中的每个元素进行分配(但由于列表立即被消耗,程序仍然有效地在恒定空间中运行):

$ ./Test2 +RTS -s
   2,400,047,200 bytes allocated in the heap
         133,012 bytes copied during GC
          27,040 bytes maximum residency (1 sample(s))
          17,688 bytes maximum slop
               1 MB total memory in use (0 MB lost due to fragmentation)
 [...]

将其与第一个程序的行为进行比较:

$ ./Test1 +RTS -s          
          47,168 bytes allocated in the heap
           1,756 bytes copied during GC
          42,632 bytes maximum residency (1 sample(s))
          18,808 bytes maximum slop
               1 MB total memory in use (0 MB lost due to fragmentation)
[...]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 GHC 使修复变得如此令人困惑? 的相关文章

  • 理解基本递归

    public static void main String args System out println factorial 5 public int factorial int n if n lt 1 return 1 else re
  • php递归合并

    我需要以某种不同的方式合并一些数组 我使用 array merge recursive 然而 有一些事情我需要改变 但我不知道如何改变 这是来自 php net 的引用 但是 如果数组具有相同的数字键 则后面的值 不会覆盖原始值 但会追加
  • 如何在haskell中用另一个字符串替换一个字符串

    我想用不同的字符串替换输入文件中的字符串 我正在寻找一种方法 但似乎我只能逐个字符地更改字符串 例如在我下面的代码中 replace String gt String replace replace x xs if x then y rep
  • 函数速度测试的奇怪结果

    我编写了一个使用递归来查找最大公因数 分母 的函数 gt gcd function a b if length a length b gt 1 warning Only scalars allowed using first element
  • RankN多态性和令人发指的克莱斯利之箭

    我不明白为什么 demobind1 的定义会产生一些编译器错误 它看起来像一个愚蠢的翻转 但不知何故 LANGUAGE GADTs LANGUAGE RankNTypes ScopedTypeVariables TypeOperators
  • 树莓派 2 上的 GHCi?

    我正在开发一些在 raspberry pi 2 上运行的 haskell 项目 以及可以使用 raspbian 7 4 1 中的 apt get 安装的 ghc 版本 但它没有 GHCi 这会阻止一些重要的包 如 Vector 的编译 我看
  • 在 ghci 下执行 `(read "[Red]") :: [Color]` 时会发生什么?

    我正在阅读以下小节现实世界 Haskell 第 6 章 类型类 http book realworldhaskell org read using typeclasses html关于一个实例Read for Color 它实现了reads
  • 如何在 Haskell Pipes 中将两个 Consumer 合并为一个?

    我使用Haskell流处理库pipes https hackage haskell org package pipes编写一个命令行工具 每个命令行操作都可以将结果输出到stdout并记录到stderr with pipes API I n
  • 为什么 mod 在表达式中给出的结果与在函数调用中给出的结果不同?

    假设有人想要计算函数 f x y x mod 3 y mod 3 mod 2 那么 如果再展开f 1 0 手动 可以得到 1 mod 3 0 mod 3 mod 2 1 然而 如果使用内联函数 结果是 let f x y x mod 3 y
  • 求一根棒可以切割的最大片数

    这是完整的问题陈述 给定一根长度为n的绳子 你需要找到最大的绳子数你可以让每一段的长度都在集合 a b c 中给定三个值a b c 我知道可以通过动态规划来实现最优解 但是 我还没有学过这个主题 我需要递归地解决这个问题 对于递归 主要的事
  • 如何在 Haskell 中使 CAF 不是 CAF?

    如何将常量应用形式变成 而不是常量应用形式 以阻止它在程序的生命周期中保留 我尝试过这种方法 Dummy parameter to avoid creating a CAF twoTrues gt Bool twoTrues map Tru
  • Haskell Fibonacci 达到最大指定数?

    我有一个已启动并正在运行的 Haskell 函数 但它做错了事情 它应该输出最多指定最大数量的斐波那契数列 像这样 fibonacciSequence 86 1 1 2 3 5 8 13 21 33 54 我的代码当前输出斐波那契数列中的前
  • Java 中具有级别顺序插入的完整二叉搜索树

    我们接到一个任务 需要编码 二叉搜索树 那个树has to be complete not perfect 这意味着所有不在最低级别或次低级别的节点都应该有 2 个子节点 而最低级别的节点应尽可能远离左侧 我们需要插入到树中等级顺序 所以如
  • 如何只修改记录的一个字段而不完全重写它? [复制]

    这个问题在这里已经有答案了 It s the second time I m tackling this problem And for the second time this is while working with the Stat
  • 我可以从 GHCi 中找到 GHC 版本吗?

    gt 我在里面输入什么GHCi发现它正在使用哪个 GHC 版本 gt import System Info gt browse arch String compilerName String compilerVersion Data Ver
  • Javascript 中的深平面多维数组[重复]

    这个问题在这里已经有答案了 我想编写一个可以深度展平给定数组的函数 例如 deepFlatten deepFlatten 1 2 3 1 2 3 deepFlatten 1 2 3 a b c 1 2 3 1 2 3 a b c 1 2 3
  • 如何让 esqueleto 为我生成 SQL 字符串?

    我怎样才能让esqueleto从a生成一个SQL字符串from陈述 的文档toRawSql说 你可以打开持久的查询日志记录 我尝试了所有可能的形式MonadLogger我可以理解 但它从未打印任何 SQL 同一文档还说 手动使用此功能 是可
  • 在 Archlinux 上使用 Vim 作为 Haskell 的 IDE 目前情况如何?

    如果可行的话 我的目标是通过 YouCompleteMe 在 Vim 中完成 Haskell 的命令 在这方面 正如您在下面看到的 我还没有找到关于如何让它发挥作用的共识 相关评论的最新评论YouCompleteMe 上的问题 https
  • 如何测试自定义 StateT 的 Monad 实例?

    我正在学习 Monad Transformers 其中一个练习要求实现 Monad 实例StateT 我想使用以下方法测试我的实现是否符合 Monad 法则validity https github com NorfairKing vali
  • Django模型递归关系

    为什么要创建递归关系 aField models ForeignKey self 这和上面的一样吗 class aClass models Model aField models ForeignKey aClass 当您希望父节点和子节点具

随机推荐

  • 如何从HTML文档中获取IMG标签代码?

    我如何得到img文本中的代码 现在 如果标签如下所示 我将获得代码和 URL text text img src image gif 但如果代码是 img src image gif target blank 然后我得到 URL image
  • 计算从 A 到 B 的动画

    我正在更新一个numeric value里面一个element通过间隔做ajax requests 为了让整个事情更加生动 我想从current的价值new一 部分地内或减少 the value超过一段时间n sec 所以基本上是这样的 d
  • 有没有办法在 MSAL.js 中查找身份验证是否遵循 MSA 还是 Azure AD

    我尝试使用此处提供的代码 https github com Azure Samples active directory javascript singlepageapp dotnet webapi v2 https github com
  • 使用 Mercurial,如果经常提交中间状态,如何与固定修订版进行比较?

    使用 Mercurial 假设我做了一个hg pull and hg up现在本地存储库和工作目录都是最新的 如果我经常提交 比如 1 天后 然后 2 天后 并且想要与现在的修订版本进行比较 该怎么办 否则 差异始终与先前提交的版本进行比较
  • 将 ruby​​ 数组转换为连续对数组

    将 ruby 数组转换为连续元素对的数组的最简单方法是什么 I mean x a b c d 预期结果 y gt a b c d Use Enumerable each slice http ruby doc org core 2 0 0
  • 使用VBA从网站上的表格中检索标签并放入Excel中

    我正在尝试从以下位置检索信息 td 网站上的标签 它有效 但我似乎无法从第二个中获取文本 td 标签在一个 tr 标签 同时使用条件语句来获取第二个标签 因为这是我认为有效的唯一方法 该代码可以很好地提取信息 我只是不知道如何在我在第一个中
  • TypeScript - 将布尔值作为 void 函数返回的函数

    如示例中所示 如果我有一个 void 函数的类型定义 则返回布尔值的函数将通过该类型检查 这是一个错误还是有正当理由 有解决方法吗 type ReturnsVoid gt void type ReturnsNumber gt number
  • Keras Convolution2D 输入:检查模型输入时出错:预期 volution2d_input_1 具有形状

    我正在努力通过这个很棒的教程 https blog keras io building powerful image classification models using very little data html关于使用 Keras 创
  • Python-用另一个单词替换单词[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有 12 个单元格的 html 表格 每个单元格都有一个要替换的单词 所有的词都是相同的 我还有一个包含 12 个元素的列表 每个元
  • 如何在 C# WEB API 中返回 JSON Web 令牌?

    我正在尝试使用 JWT 来保护用 C 编写的 WEB API 但我对一些事情感到困惑 根据我的理解 流程应该是这样的 客户端从某些客户端应用程序 Angular NET Mobile 等 向 Web API 提供用户名 密码 Web API
  • 哪种传感器适合旋转 Android 手机?

    想象一下你指着电视 您手里紧握着手机 现在 旋转手腕 我需要使用哪个传感器来检测这样的运动 陀螺仪 方向 加速度计 传感器TYPE MAGNETIC FIELD and TYPE ACCELEROMETER可以很好地检测到这一点 如TYPE
  • PySide:QPushButton 按下后保持突出显示

    在我的工具中 当用户按下按钮时 会创建一个弹出窗口 我的问题是 用户按下打开窗口的按钮在弹出窗口创建时保持突出显示 就像我将鼠标悬停在它上面一样 并且即使在弹出窗口被删除后仍然保持这种状态 我实际上喜欢弹出窗口处于活动状态时的此突出显示 它
  • 相当于 ASP.NET 中的 ASP.NET MVC TempData

    在 ASP NET MVC 中 有一个 TempData 可以将数据一次从一个页面传递到另一页面 在 ASP NET 中这相当于什么 没有直接的等效项 即仅传递到下一页的数据 您可以使用Session并在接收页面将其清除
  • 保存/提交时重新加载 jqGrid

    我有以下代码可以在双击时进入内联编辑 ondblClickRow function row id if row id null Products jqGrid restoreRow last selected row Products jq
  • 在 Javascript 中模拟 window.location.href

    我对一个使用 window location href 的函数进行了一些单元测试 这并不理想 我宁愿将其传递进去 但在实现中这是不可能的 我只是想知道是否可以模拟这个值而不实际导致我的测试运行器页面实际转到该 URL window loca
  • 对于此场景,在 SQL 中连接多个表

    这是我的表结构 我有3张桌子 会员表 评论表 评论如表 表结构可以在下图中找到 表 会员 user id full name email password image join date 表 专辑 评论
  • 使用Python/Boto/Django构建策略直接上传到S3

    到目前为止 我已经经历了这个问题的多次迭代 搜索了许多不同的示例 并且已经阅读了所有文档 我正在尝试结合 Plupload http www plupload com http www plupload com 与 AWS S3 直接发布方
  • 带有用户输入和选择变量的 Jenkinsfile

    我想使用新的 Jenkinsfile 来完成新的工作 我有 jenkinsfile 它位于单独的存储库中 我从另一个 GitLab 存储库获取分支git ls remote在bash中 我将它们存储在变量中 branch1 branch2
  • Ionic 3 - cocoapods 的 xcode 错误

    我尝试构建一个带有推送通知的 ionic 3 应用程序 但我在 iOS 部署方面遇到了一些问题 我在 xcode 中遇到了 3 个错误 diff Podfile lock No such file or directory diff Man
  • 为什么 GHC 使修复变得如此令人困惑?

    查看 GHC 源代码我可以看到定义fix is fix a gt a gt a fix f let x f x in x 在一个例子中fix像这样使用 fix f x gt let x x 1 in x f x 这基本上会产生一系列加一到无