Javascript 如何使用算法W进行类型检查递归定义?
我正在用JavaScript实现: 实现上述规则的函数是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
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处理