【问题标题】:Understanding recurive let expression in lambda calculus with Haskell, OCaml and nix language使用 Haskell、OCaml 和 nix 语言理解 lambda 演算中的递归 let 表达式
【发布时间】:2020-12-05 02:56:17
【问题描述】:

我试图通过比较其他函数式编程语言和概念中的类似功能来了解 recursive set 在内部是如何运作的。

我可以在wiki 找到它。在那,我需要知道 Y 组合子,不动点。我可以在wiki 得到它。

那么,现在我开始在 Haskell 中应用它。

哈斯克尔

它是easy。但我想知道幕后花絮。

*Main> let x = y; y = 10; in x
10

【问题讨论】:

  • 您想在给变量赋值之前使用它?
  • @Shawn 是的。在nix set中,如果没有rec,就不知道后面要赋值的变量。
  • 我很确定你不能在 ocaml 中做到这一点。
  • @Shawn 因为eager eval?比如Java、C++、Python?
  • 当你说“我试图理解递归集是如何在函数中运行的(不仅仅是范围检查)。”,我不明白你的意思。您的意思是“功能操作”还是“以功能语言操作”?以及“操作”是什么意思?如“我如何使用”或“操作语义是什么”或“它如何在内部运行”?

标签: haskell nix letrec


【解决方案1】:

当您使用 Haskell 或 Nix 等惰性函数式语言编写 a = f b 时,其含义比赋值更强大。 af b 将是同一件事。这通常称为绑定

我将专注于一个 Nix 示例,因为您正在专门询问递归集。

一个简单的属性集

我们先来看一个属性集的初始化。当要求 Nix 解释器评估此文件时

{ a = 1 + 1; b = true; }

它解析它并返回这样的数据结构

{ a = <thunk 1>; b = <thunk 2>; }

其中一个 thunk is 一个对相关语法树节点的引用和一个对“环境”的引用,它的行为就像一个从标识符到它们的值的字典,尽管实现起来更有效。

也许我们评估这个文件的原因是因为你请求了nix-build,它不仅会询问文件的值,还会在它看到它是一个时遍历属性集。所以nix-build 将要求a 的值,这将根据其thunk 计算。计算完成后,为保存 thunk 的内存分配实际值,type = tIntvalue.integer = 2

递归属性集

Nix 有一个特殊的语法,它结合了属性集构造语法 ({ }) 和 let-binding 语法的功能。当您使用一些共享值构造属性集时,这可以避免一些重复。

例如

let b = 1 + 1;
in { b = b; a = b + 5; }

可以表示为

rec { b = 1 + 1; a = b + 5; }

评估以类似的方式进行。

首先,求值器返回包含所有 thunk 的属性集的表示,但这次 thunk 引用 new environmentincludes 在现有词法范围之上的所有属性。

请注意,所有这些表示都可以在执行最少的工作时构建。

nix-build 按字母顺序遍历 attrsets,因此它将首先评估 a。这是一个引用 + 语法节点和其中包含 b 的环境的 thunk。评估这一点需要评估 b 语法节点(ExprVar),它引用环境,我们在其中找到 1 + 1 thunk,它像以前一样更改为 2tInt

如您所见,这种创建 thunk 但仅在需要时才对其进行评估的过程确实是懒惰的,并且允许我们拥有具有自己的范围规则的各种语言结构。

Haskell 实现通常遵循类似的模式,但可以编译代码而不是解释语法树,并将所有变量引用完全解析为常量内存偏移。 Nix 尝试在某种程度上做到这一点,但它必须能够依靠字符串,因为不建议使用的 with 关键字会使范围动态化。

【讨论】:

  • a = a + 5; in let b = 1 + 1; in { b = b; a = a + 5; } -> a = b + 5; in rec { b = 1 + 1; a = b + 5; }。为什么a 转换为b
  • 我在改进示例以适应文本时弄乱了示例。修好了。
【解决方案2】:

我自己猜测几件事。

  • 在 eagar 评估语言中,我必须在使用前声明。所以声明的顺序很简单。
int x = 10;
int y = x;
  • 仅适用于 Nix 语言

wiki 中,虽然let ... in 与Haskell 进行了比较,但没有与Haskell 进行任何概念比较。

  • 词法范围

all variables are lexically scoped.

  • 相互递归

https://en.wikipedia.org/wiki/Let_expression#Mutually_recursive_let_expression

【讨论】:

    猜你喜欢
    • 2019-01-29
    • 2019-06-01
    • 1970-01-01
    • 2018-02-14
    • 2011-10-31
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多