当前位置: 首页 > 知识库问答 >
问题:

互递归函数的Hindley Milner类型推断

微生俊捷
2023-03-14

我正在制作一种强类型的玩具函数式编程语言。它使用Hindley Milner算法作为类型推断算法。

在实现该算法时,我有一个问题,即如何推断相互递归函数的类型。

let rec f n = if n == 0 then 0 else g (n - 1)
let rec g n = if n == 0 then 0 else f (n - 1)

fg是相互递归的函数。现在,当类型检查器推断函数f的类型时,它也应该能够推断函数g的类型,因为它是一个子表达式

但是,在那一刻,函数g还没有定义。因此,显然,类型检查器甚至不知道函数g的存在,以及函数g的类型。

真实世界的编译器/Intepreter使用哪些解决方案?

共有1个答案

宗政昱
2023-03-14

在OCaml中,相互递归的值由关键字分隔,而不是另一个let rec。当类型系统到达递归定义时,它会将所有递归名称添加到环境中,然后像往常一样继续。

更新(感谢K.A.Buhr):

完全可以创建类型为a的新变量(a是新的),然后将其统一。确保在正确的位置(通常在定义之后)概括变量。

 类似资料:
  • 假设我编写这样的代码: 我如何让Kotlin优化这些相互递归的函数,以便在不抛出StackOverflower错误的情况下运行main?tailrec关键字适用于单函数递归,但没有更复杂的功能。我还看到一个警告,在使用关键字tailrec的地方没有找到尾部调用。也许这对编译器来说太难了?

  • 标准 ML 没有多态递归。在模块语言中添加递归允许我们使用内函子的固定点将多态递归恢复为一种特殊情况。例如: 众所周知,多态递归使得类型推理不可判定。然而,函子定义已经包含部分类型信息,即其参数的签名。这些信息足以使类型推理再次可判定吗?

  • 查看我在某处(这里是游乐场)找到的这个Typescript4.2片段: 我的头不能绕着它。TS如何处理这件事?它怎么不卡在无限递归里?具体地说,对于和的情况,悬停在变量上显示TS将类型解析为和。这是怎么回事?

  • 我试着用拉库OOP写杨彦湛的拉库谜语比赛答案。Raku类系统非常直观,在我遇到递归函数之前,一切都很有魅力。这是类和函数的代码版本: 对于$tigers=4,函数给出: 另一方面,类总是陷入无限循环。我相信函数和类之间的区别在于这行代码: 我不清楚这是因为格式错误的递归语法还是函数和类之间类型约束的差异。

  • (Scala 2.11.8) 我有一个类似GenTableLike的特征,具有复杂的自递归类型签名,它定义了连接兼容表实现的方法。我还有一个层次结构 下面是一个稍微简化的片段,其中问题仍然存在: 我是不是做错了什么? 自类型和转置类型用于定义函数返回类型。我还有一个IndexedTable实现定义如下,所以我不能返工自类型以接受3个参数

  • 问题 你想在一个函数中调用相同的函数。 解决方案 使用一个命名函数: ping = -> console.log "Pinged" setTimeout ping, 1000 若为未命名函数,则使用 @arguments.callee@: delay = 1000 setTimeout((-> console.log "Pinged" setTimeout arg