OCaml:使用 first-class 模块和存在类型进行递归
OCaml: recursion with first-class modules and existential type
我正在尝试制作一个交替使用两个模块(相同类型)的函数,同时深入递归。我将模块作为参数传递,但当我向模块添加存在类型时,一切都出错了。让我有点惊讶的是,如果我使函数成为非递归的(就像我发现的所有远程相似的例子一样),它就可以工作。
这是我认为的最小示例(只是传递了一个模块):
module type TEST =
sig
type t
val foo : t -> unit
end
let rec foo
(type a)
(module Test : TEST with type t = a)
(arg : a) : unit =
(* Test.foo arg *) (* <- works *)
(* I tried various type annotations, but none worked: *)
foo (module Test : TEST with type t = a) (arg : a)
示例的错误消息:
Error: This expression has type
(module TEST with type t = a) -> a -> 'b
but an expression was expected of type
(module TEST with type t = a) -> a -> 'b
The type constructor a would escape its scope
为什么它不起作用,我该怎么做才能让它起作用?
不确定是否完全理解您的错误,但是在进行递归时,通常最好将类型注释放在最高级别。
这是一个有效的版本:
module type TEST =
sig
type t
val foo : t -> unit
end
let rec foo : type a. (module TEST with type t = a) -> a -> unit
= fun (module Test) arg ->
if true
then foo (module Test) arg
else Test.foo arg
我正在尝试制作一个交替使用两个模块(相同类型)的函数,同时深入递归。我将模块作为参数传递,但当我向模块添加存在类型时,一切都出错了。让我有点惊讶的是,如果我使函数成为非递归的(就像我发现的所有远程相似的例子一样),它就可以工作。
这是我认为的最小示例(只是传递了一个模块):
module type TEST =
sig
type t
val foo : t -> unit
end
let rec foo
(type a)
(module Test : TEST with type t = a)
(arg : a) : unit =
(* Test.foo arg *) (* <- works *)
(* I tried various type annotations, but none worked: *)
foo (module Test : TEST with type t = a) (arg : a)
示例的错误消息:
Error: This expression has type
(module TEST with type t = a) -> a -> 'b
but an expression was expected of type
(module TEST with type t = a) -> a -> 'b
The type constructor a would escape its scope
为什么它不起作用,我该怎么做才能让它起作用?
不确定是否完全理解您的错误,但是在进行递归时,通常最好将类型注释放在最高级别。 这是一个有效的版本:
module type TEST =
sig
type t
val foo : t -> unit
end
let rec foo : type a. (module TEST with type t = a) -> a -> unit
= fun (module Test) arg ->
if true
then foo (module Test) arg
else Test.foo arg