Javascript 如何使用算法W进行类型检查递归定义?

Javascript 如何使用算法W进行类型检查递归定义?,javascript,haskell,ocaml,type-inference,coq,Javascript,Haskell,Ocaml,Type Inference,Coq,我正在用JavaScript实现: 实现上述规则的函数是typecheck,它具有以下签名: typecheck::(上下文,Expr)->Monotype 其定义如下: 函数类型检查(上下文、表达式){ 开关(expression.type){ 案例“Var”: var name=expression.name; 变量类型=上下文[名称]; 返回仪表(类型); 案例“应用程序”: var fun=typecheck(context,expression.fun); var dom=type

我正在用JavaScript实现:

实现上述规则的函数是
typecheck
,它具有以下签名:

typecheck::(上下文,Expr)->Monotype
其定义如下:

函数类型检查(上下文、表达式){
开关(expression.type){
案例“Var”:
var name=expression.name;
变量类型=上下文[名称];
返回仪表(类型);
案例“应用程序”:
var fun=typecheck(context,expression.fun);
var dom=typecheck(context,expression.arg);
var cod=新变量;
统一(乐趣,abs(dom,cod));
返回cod;
案例“Abs”:
var param=expression.param;
var env=Object.create(上下文);
var dom=env[param]=新变量;
var cod=类型检查(env,expression.result);
返回abs(dom,cod);
案例“Let”:
var赋值=expression.assignments;
var env=Object.create(上下文);
for(赋值中的变量名称){
var值=赋值[名称];
变量类型=类型检查(上下文、值);
env[name]=gen(上下文,类型);
}
返回类型检查(env,expression.result);
}
}
关于数据类型:

  • 上下文是将标识符映射到多类型的对象

    type Context=映射字符串Polytype
    
  • 表达式由以下代数数据类型定义:

    data Expr=Var{name::String}
    |App{fun::Expr,arg::Expr}
    |Abs{param::String,result::Expr}
    |让{assignments::Map String Expr,result::Expr}
    |Rec{assignments::Map String Expr,result::Expr}
    
  • 此外,我们有以下功能,这些功能是算法所要求的,但不是问题所必需的:

    inst::Polytype->Monotype
    abs::(单式,单式)->单式
    gen::(上下文,单类型)->多类型
    
    inst
    函数专门用于多类型,而
    gen
    函数概括了单类型

    无论如何,我想扩展我的
    typecheck
    功能,以允许:

    其中:

  • 然而,我陷入了鸡和蛋的问题。第一个上下文的假设是
    v_1:τ_1,…,v_n:τ_n
    。此外,它意味着
    e_1:τ_1,…,e_n:τ_n
    。因此,您首先需要创建上下文以查找
    e_1,…,e_n
    的类型,但要创建上下文,您需要查找
    e_1,…,e_n
    的类型

    你如何解决这个问题?我在考虑将新的单类型变量分配给标识符
    vu 1,…,vu n
    ,然后将每个单类型变量与其各自的类型统一起来。这是OCaml用于其
    let rec
    绑定的方法。但是,此方法不会产生最通用的类型,如以下OCaml代码所示:

    $ocaml
    OCaml版本4.02.1
    #设rec foo x=foo(bar true)
    条x=x;;
    val foo:bool->'a=
    值栏:布尔->布尔=
    
    但是,GHC计算的是最一般的类型:

    $ghci
    GHCi,7.10.1版:http://www.haskell.org/ghc/  :? 求救
    前奏曲>让foo x=foo(bar True);棒x=x
    前奏曲>:t foo
    foo::Bool->t
    前奏曲>:t小节
    棒::t->t
    
    如您所见,OCaml推断类型
    val bar:bool->bool
    ,而GHC推断类型
    bar::t->t
    。Haskell如何推断出最通用的函数类型
    bar

    我从@augustss的回答中了解到递归多态函数的类型推断是不可判定的。例如,如果没有其他类型注释,Haskell无法推断以下
    size
    函数的类型:

    数据嵌套a=Epsilon | Cons a(嵌套[a])
    大小ε=0
    大小(Cons_xs)=1+大小xs
    
    如果我们指定类型签名
    size::Nested a->Int
    ,那么Haskell接受该程序


    然而,如果我们只允许代数数据类型的子集,那么数据定义
    嵌套的
    将无效,因为它不是归纳的;如果我没有弄错的话,那么归纳多态函数的类型推断确实是可判定的。如果是这样,那么用于推断多态归纳函数类型的算法是什么?

    您可以使用显式递归对其进行类型检查,使用具有类型
    (a->a)->a
    的原语
    fix
    。您可以手动或自动插入修复程序


    如果你想扩展类型推断,那也很容易。当遇到递归函数f时,只需生成一个新的统一变量,并将此类型的f放入环境中。在对主体进行类型检查之后,将主体类型与此变量统一,然后像往常一样进行泛化。我想这就是你的建议。它不允许您推断多态递归,但这通常是不可判定的

    我刚刚在OCaml中测试了以下声明,
    let rec foo x=foo(bar true)和bar x=x。推断出的类型为
    val-foo:bool->'a
    val-bar:bool->bool
    。然而,在GHC中,当我测试
    时,让foo x=foo(bar True);bar x=x
    推断的类型更一般,
    foo::Bool->t
    bar::t->t
    。我想知道GHC是如何推断出最通用的函数类型
    bar
    。您知道吗?在您的示例中,条形图不是递归的,它的类型可以单独推断。Haskell类型检查首先采用相互递归的定义组,并将它们划分为强连接的组件。然后,对每个组件进行ow处理