假设我有一个由模块 F
参数化的模块 M
:
module M (F : sig type id type data end) =
struct
type idtype = F.id
type datatype = F.data
type component = { id : idtype; data : datatype }
let create id data = { id; data }
let get_comp_data comp = comp.data
let get_comp_id comp = comp.id
end
所以我这样使用它:
module F1 = struct type id = int type data = float end
module MF1 = M(F1)
let comp = MF1.create 2 5.0
let id = MF1.get_comp_id comp
现在,如果我希望 M
匹配签名 S
:
module type S =
sig
type idtype
type datatype
type component
val create : idtype -> datatype -> component
val get_comp_data : component -> datatype
val get_comp_id : component -> idtype
end
module F1 = struct type id = int type data = float end
module MF1 = (M(F1) : S)
let comp = MF1.create 2 5.0
let id = MF1.get_comp_id comp
这里困扰我的是,为了定义 get_comp_data
和 get_comp_id
,我需要
在模块S
中指定idtype
和datatype
;现在想象一下,我在 M
中有其他记录类型及其自己的类型,我将在 S
中指定十几种类型?有没有更简单的方法来避免这种情况?
最佳答案
执行此操作的自然方法是在定义站点而不是使用站点密封模块。那么你只需要表达一次类型共享:
module M (F : sig type id type data end) :
S with type idtype = F.id and datatype = F.data
= struct ... end
如果您的仿函数参数更复杂,那么您也可以只共享整个模块而不是单个类型。例如:
module type TYPES = sig type id type data (* ...and more... *) end
module type S =
sig
module Types : TYPES
type component
val create : Types.id -> Types.data -> component
val get_comp_data : component -> Types.data
val get_comp_id : component -> Types.id
end
module M (F : TYPES) : S with module Types = F
= struct ... end
或者您甚至可以通过将签名嵌套到另一个仿函数中来参数化签名本身:
module type TYPES = sig type id type data (* ...and more... *) end
module S (F : TYPES) =
struct
module type S =
sig
type component
val create : F.id -> F.data -> component
val get_comp_data : component -> F.data
val get_comp_id : component -> F.id
end
end
module M (F : TYPES) : S(F).S
= struct ... end
关于module - 如何定义模块签名,其模块实现由仿函数参数化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10542079/