Ocaml first-class 模块和扩展变体
Ocaml first-class module and extended variant
我尝试通过实现这段代码来使用 first-class 模块:
module Component =
struct
type t_data = ..
module type S =
sig
type t
val create : t -> t_data
end
module Make (C: sig type t end) =
struct
type t = C.t
type t_data += T of C.t
let create data = T data
end
end
let create m data =
let module M = (val m : Component.S) in M.create data
(* The type constructor M.t would escape its scope *)
我也会尝试这个替代方案,但我不知道如何在模块 S 中添加扩展类型 t_data :
let create' m data =
let module M = (val m : Component.S) in M.T data
(* Unbound constructor M.T *)
我正在使用 bucklescript,谢谢!
你只需要一些额外的注释来说服类型检查器:
let create (type t0) (m : (module Component.S with type t = t0)) data =
let module M = (val m) in M.create data
可简写为:
let create (type t0) (module M : Component.S with type t = t0) data =
M.create data
(type t)
注释引入了 local 抽象数据类型。在函数外,这个类型变成了通用类型变量,因此给定类型:
val create : (module Component.S with type t = 'a) -> 'a -> Component.t_data
您可以像使用任何其他类型一样使用本地抽象类型,特别是您也可以将其放在本地定义的模块中:
let inject (type t0) data =
let module M0 = struct type t = t0 end in
let module M = Component.Make(M0) in
M.create data
val make : 'a -> Component.t_data
我尝试通过实现这段代码来使用 first-class 模块:
module Component =
struct
type t_data = ..
module type S =
sig
type t
val create : t -> t_data
end
module Make (C: sig type t end) =
struct
type t = C.t
type t_data += T of C.t
let create data = T data
end
end
let create m data =
let module M = (val m : Component.S) in M.create data
(* The type constructor M.t would escape its scope *)
我也会尝试这个替代方案,但我不知道如何在模块 S 中添加扩展类型 t_data :
let create' m data =
let module M = (val m : Component.S) in M.T data
(* Unbound constructor M.T *)
我正在使用 bucklescript,谢谢!
你只需要一些额外的注释来说服类型检查器:
let create (type t0) (m : (module Component.S with type t = t0)) data =
let module M = (val m) in M.create data
可简写为:
let create (type t0) (module M : Component.S with type t = t0) data =
M.create data
(type t)
注释引入了 local 抽象数据类型。在函数外,这个类型变成了通用类型变量,因此给定类型:
val create : (module Component.S with type t = 'a) -> 'a -> Component.t_data
您可以像使用任何其他类型一样使用本地抽象类型,特别是您也可以将其放在本地定义的模块中:
let inject (type t0) data =
let module M0 = struct type t = t0 end in
let module M = Component.Make(M0) in
M.create data
val make : 'a -> Component.t_data