Types 用于类型推断的OCaml LET REC类型规则

Types 用于类型推断的OCaml LET REC类型规则,types,ocaml,programming-languages,Types,Ocaml,Programming Languages,我目前正在尝试使用静态类型系统实现一个类型分析器,该系统使用OCaml语言实现 我使用的算法是首先生成类型方程,然后使用统一算法求解这些方程。除了递归的letrecexp绑定类型之外,我已经能够很好地实现代码 以下是完整的代码: type program=exp 和exp= |整数的个数 |VAR中的VAR |exp*exp之和 |exp*exp的差值 |多重经验*exp |exp*exp的DIV |经验零点 |如果为exp*exp*exp |让我们看看var*exp*exp |var*var*

我目前正在尝试使用静态类型系统实现一个类型分析器,该系统使用OCaml语言实现

我使用的算法是首先生成类型方程,然后使用统一算法求解这些方程。除了递归的
letrecexp
绑定类型之外,我已经能够很好地实现代码

以下是完整的代码:

type program=exp
和exp=
|整数的个数
|VAR中的VAR
|exp*exp之和
|exp*exp的差值
|多重经验*exp
|exp*exp的DIV
|经验零点
|如果为exp*exp*exp
|让我们看看var*exp*exp
|var*var*exp*exp的LETREC
|var*exp的FUNC
|调用exp*exp
和var=string
;;
typetyp=TypeInt | TypeBool | TypeFun of typ*typ | TypeVar of tyvar
和tyvar=string
;;
类型方程=(典型*典型)列表;;
模块类型env=struct
类型t=var->typ
让空
=乐趣->提升(失败“类型环境为空”)
让我们扩展(x,t)tenv
=乐趣y->如果x=y,则t else(tenv y)
让我们找到tenvx=tenvx
结束
;;
设typevar_num=ref 0;;
让new_typevar()=(typevar_num:=!typevar_num+1;(typevar(“t”^string_of_int!typevar_num));;
让rec生成公式:TypeEnv.t->exp->typ->type\u公式
=乐趣无穷->
匹配
|NUM n->[(ty,TypeInt)]
|变量x->[(ty,TypeEnv.find tenv x)]
|求和(e1,e2)->让eq1=[(ty,TypeInt)]在
设eq2=生成_eqnstenv e1 TypeInt in
设eq3=在中生成eqns tenv e2 TypeInt
eq1@eq2@eq3
|DIFF(e1,e2)->让eq1=[(ty,TypeInt)]进入
设eq2=生成_eqnstenv e1 TypeInt in
设eq3=在中生成eqns tenv e2 TypeInt
eq1@eq2@eq3
|DIV(e1,e2)->让eq1=[(ty,TypeInt)]进入
设eq2=生成_eqnstenv e1 TypeInt in
设eq3=在中生成eqns tenv e2 TypeInt
eq1@eq2@eq3
|MULT(e1,e2)->让eq1=[(ty,TypeInt)]进入
设eq2=生成_eqnstenv e1 TypeInt in
设eq3=在中生成eqns tenv e2 TypeInt
eq1@eq2@eq3
|ISZERO e->让eq1=[(ty,TypeBool)]进入
设eq2=生成eqns tenv e TypeInt in
eq1@eq2
|如果(e1,e2,e3)->让eq1=生成
设eq2=生成eqns tenv e2 ty in
设eq3=gen_方程tenv e3 ty in
eq1@eq2@eq3
|让(x,e1,e2)->让t1=in中的新类型变量()
设eq1=生成tenv e1 t1 in
设eq2=generate_eqns(TypeEnv.extend(x,t1)tenv)e2 tyin
eq1@eq2
|LETREC(f,x,e1,e2)->(*让t1=new_typevar()在
让new_env=TypeEnv.extend(x,t1)tenv in
设eq1=生成新的eqns_env f*)
|FUNC(x,e)->让t1=new_typevar()进入
让t2=new_typevar()进入
让eq1=[(ty,TypeFun(t1,t2))]在
设eq2=generate_eqns(TypeEnv.extend(x,t1)tenv)e t2 in
eq1@eq2
|调用(e1,e2)->让t1=new_typevar()进入
设eq1=生成_eqnstenv e1(TypeFun(t1,ty))in
设eq2=生成eqns tenv e2 t1 in
eq1@eq2
;;

执行类型方程生成的主要功能是
generate\u eqns
。它以空类型环境、表达式和初始类型作为参数,并按如下方式调用:
generate\u eqns TypeEnv.empty(NUM 3)(new\u typevar())

我在实现
LETREC
递归调用时遇到问题。我一直在网上寻找资料,但它们似乎对我的问题没有太大帮助

特别是,我一直试图从编程语言(3e)的要点中分析这个类型规则-Friedman&Wand:

有人能给我一些建议吗


谢谢。

所以我浏览了你的代码,这是未经测试的,等等。但乍一看,我想应该是这样的


谢谢你,这实际上是一个完美的答案。我没想到会有一个完整的答案,非常感谢。实际上做了一个小改动,表达式的形式是e2中的
let rec f x=e1
,因此
x
只出现在
e1
中,而不出现在
e2
中。因此
e2
的环境应该只添加
f
,而不是
x
  | LETREC (f, x, e1, e2) ->
     let tx  = new_typevar ()    in (** type of x   **)
     let tfx = new_typevar ()    in (** type of f x **)
     let tf  = TypeFun (tx, tfx) in (** type of f   **)
     let tenvf  = TypeEnv.extend (f, tf) tenv  in (** f in env **) 
     let tenvxf = TypeEnv.extend (x, tx) tenvf in (** x and f in env **) 
     let eq1 = generate_eqns tenvxf e1 tfx in (** type e1 = type (f x) **)
     let eq2 = generate_eqns tenvf  e2 ty  in (** type e2 = typ **)
         eq1 @ eq2