Lho*_*ooq 2 polymorphism ocaml first-class-modules
我只想有一个在 Hashtbls 上通用的简单函数,所以我写了这个:
let iter_htbl (type a) (module H : Hashtbl.S with type key = a) htbl =
H.iter (fun _key _v -> ()) htbl
Run Code Online (Sandbox Code Playgroud)
这给了我以下错误:
53 | H.iter (fun _key _v -> ()) htbl
^^^^
Error: This expression has type 'a but an expression was expected of type
'b H.t
The type constructor H.t would escape its scope
Run Code Online (Sandbox Code Playgroud)
如果我写:
53 | H.iter (fun _key _v -> ()) htbl
^^^^
Error: This expression has type 'a but an expression was expected of type
'b H.t
The type constructor H.t would escape its scope
Run Code Online (Sandbox Code Playgroud)
新错误(但几乎相同):
52 | let iter_htbl (type a b) (module H : Hashtbl.S with type key = a) (htbl : b H.t)
^^^^^^^^^^^^^^
Error: This pattern matches values of type b H.t
but a pattern was expected which matches values of type 'a
The type constructor H.t would escape its scope
Run Code Online (Sandbox Code Playgroud)
对于我想要实现的目标有解决方案吗?
当然,在我的简单情况下我可以写
let iter_htbl (type a b) (module H : Hashtbl.S with type key = a) (htbl : b H.t)
=
H.iter (fun _key _v -> ()) htbl
Run Code Online (Sandbox Code Playgroud)
但如果我想使用多个函数,H这不是一个有用的解决方案。
那是行不通的。不幸的是,OCaml 的类型系统无法直接表达这一点。这将需要更高级的多态性,而 ML 核心语言不具备这一点:
\nlet iter_htbl (type key) (type 'a htbl) (type a) (module H : Hashtbl.S with type key = key with type 'a t = 'a htbl) (htbl : a htbl) = ...\nRun Code Online (Sandbox Code Playgroud)\n存在(type 'a htbl)语法错误 \xe2\x80\x93 是有原因的,因为参数化类型的这种多态性不能轻易地与类型推断相协调(至少在没有某些限制的情况下),因为它需要在一般情况,无法判定。
在 ML 中抽象参数化类型(如 Ht)的唯一方法是提升到模块级别并编写函子:
\nmodule IterHtbl (H : Hashtbl.S) (T : sig type a val htbl : a H.t end) =\nstruct\n let it = H.iter (fun _ _ -> ()) T.htbl\nend\nRun Code Online (Sandbox Code Playgroud)\n这是可行的,因为模块的类型更加明确。
\n