Functional programming Hindley-Milner型系统中letrec的正确形式?

Functional programming Hindley-Milner型系统中letrec的正确形式?,functional-programming,type-inference,lambda-calculus,hindley-milner,Functional Programming,Type Inference,Lambda Calculus,Hindley Milner,我很难理解维基百科上给出的HM系统的letrec定义,这里: 对我来说,这条规则大致可以转化为以下算法: 推断letrec定义部分中所有内容的类型 为每个定义的标识符分配临时类型变量 使用临时类型递归处理所有定义 成对使用原始临时变量统一结果 关闭(对于所有)推断的类型,将它们添加到基础(上下文)中,并使用它推断表达式部分的类型 我在这样的程序中遇到了问题: letrec p = (+) --has type Uint -> Uint -> Uint x = (letr

我很难理解维基百科上给出的HM系统的letrec定义,这里:

对我来说,这条规则大致可以转化为以下算法:

  • 推断
    letrec
    定义部分中所有内容的类型
  • 为每个定义的标识符分配临时类型变量
  • 使用临时类型递归处理所有定义
  • 成对使用原始临时变量统一结果
  • 关闭(对于所有)推断的类型,将它们添加到基础(上下文)中,并使用它推断表达式部分的类型
  • 我在这样的程序中遇到了问题:

    letrec
     p = (+)     --has type Uint -> Uint -> Uint
     x = (letrec
           test = p 5 5
         in test)
    in x
    
    我观察到的行为如下:

    • p
      的定义获取临时类型
      a
    • x
      的定义也得到了一些临时类型,但这不在我们的范围之内
    • x
      中,
      test
      的定义获取一个临时类型
      t
    • p
      使用变量的HM规则从范围中获取临时类型
      a
    • (f 5)
      由HM规则处理以供应用,结果类型为
      b
      (以及(
      a
      Uint->b
      相统一)
    • ((p 5)5)
      通过相同的规则进行处理,导致更多的统一和类型
      c
      a
      现在的结果与
      Uint->Uint->c
    • 现在,对于所有c.c
    • test中
      的变量test根据变量的HM规则,获取具有新变量的类型实例(或所有c.c
      ),从而生成
      test::d
      (与
      test::t
      统一)
    • 产生的
      x
      具有有效的
      d
      (或
      t
      ,取决于统一的情绪)
    问题是:
    x
    显然应该有类型
    Uint
    ,但我认为这两个类型不可能统一生成该类型。当
    test
    的类型关闭并再次实例化时,会丢失信息,我不确定如何克服或连接替换/统一

    你知道该如何修正算法以正确键入
    x::Uint
    吗?或者这是HM系统的一个属性,它根本不会键入这种情况(我对此表示怀疑)

    请注意,对于标准的
    let
    ,这完全可以,但我不想用
    let
    无法处理的递归定义混淆示例


    提前感谢您回答我自己的问题:

    Wiki上的定义是错误的,尽管它至少在某种程度上适用于类型检查

    将递归添加到HM系统中最简单、最正确的方法是使用
    fix
    谓词,定义为
    fix f=f(fix f)
    并键入
    forall a.(a->a)->a
    。相互递归由双不动点处理,等等


    Haskell解决问题的方法(在中描述)是(大致)为所有函数派生一个不完整的类型,然后再次运行派生以相互检查。

    wiki上的定义在我看来确实是正确的。你能指出错误的地方吗?