递归调用的函数类型推断

时间:2013-03-15 08:47:48

标签: f# type-inference

我正在尝试实现一种自定义语言,允许从最后一个语句推断出函数返回类型。但是,当发现直接或间接递归函数调用时,类型推断系统显然会失败。

func factorial(a:int) -> 
    if a == 0
        1
    else
        a * factorial(a - 1)

例如,即使参数类型未指定,F#也会这样做:

let rec fact i =
    if i = 0 then 1 else i * fact (i-1)

这个系统如何运作?

1 个答案:

答案 0 :(得分:13)

F#类型检查器使用Damas-Hindley-Milner类型推断算法。阶乘的例子大致可以解释如下:

  • fact的声明中,我们的格式为tx -> tytx = t(i),其中t(i)是值i的类型。

  • 在同等性检查中,由于val (=): 'T -> 'T -> bool我们还有t(i) = t(0) = int

  • then分支机构,我们得到另一个约束ty = t(1) = int
  • 来自else分支,普通(*)运算符为'T -> 'T -> 'T,因此我们得到t(i) = ty

基于约束集:

tx = t(i)
t(i) = t(0) = int
ty = t(1) = int
t(i) = ty

使用统一,我们到达tx = ty = int并将fact的类型推断为int -> int。这也意味着如果你改变if/then/else中的子句顺序(通过反转条件),类型推断仍然可以正常工作。

那就是说,这是类型推理算法的一个非常简单的例子。 您可以按照上面的维基百科链接阅读更多相关信息。

为了将算法应用于您的自定义语言,您可以在各种函数式编程书籍中找到实现。有关详细信息,请参阅此主题Damas-Hindley-Milner type inference algorithm implementation