首页 > 解决方案 > OCaml 坚持认为函数不是多态的,但不指定类型

问题描述

是否可以明确写下非多态但延迟统一的类型,如下划线类型?

因此,OCaml 有时会在类型检查过程中生成一个顶级打印的类型,该类型带有前导下划线(例如_a)。具体来说,这些出现在实例化空对象时Hashtbl.t和其他一些情况下。

# Hashtbl.create 1;;
- : ('_a, '_b) Hashtbl.t = <abstr>

但是,用户不能在源代码中明确引用这些类型。

# (5: int);;
- : int = 5
# (5: 'a);;
- : int = 5
# (5: '_a);;
Error: The type variable name '_a is not allowed in programs

您可以通过利用 OCaml 中缺乏更高级别的多态性来创建显式非多态函数

# let id = snd ((), fun y -> y);;
val id : '_a -> '_a = <fun>
# (fun () -> fun y -> y) ();;
- : '_a -> '_a = <fun>

我希望能够做类似的事情

let id : <some magical type> = fun x -> x

并且不依赖于将来可能会消失的类型系统的限制。

标签: ocaml

解决方案


您可以使用引用不可概括的事实。

# let id = let rx = ref [] in fun x -> rx := [x]; rx := []; x;;
val id : '_weak1 -> '_weak1 = <fun>

我认为引用的这种属性不太可能改变。

我假设你想要的是这个版本id在第一次实际使用时假设一个单态类型:

# id "yes";;
- : string = "yes"
# id;;
- : string -> string = <fun>

如果您在实际代码中使用它,则需要在其模块结束之前获取具体类型。您不能将弱类型变量保留为未定义,否则会出现此错误:

Error: The type of this expression, '_weak1 -> '_weak1,
       contains type variables that cannot be generalized

推荐阅读