Как определить сигнатуру модуля, реализация модуля которого параметризована функтором

Допустим, у меня есть модуль M, параметризованный модулем F:

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 мне нужно указать idtype и datatype в модуле S; теперь только представьте, что у меня есть другие типы записей в M с их собственными типами, у меня будет дюжина типов для указания в S? Есть ли более простой способ избежать этого?


person codablank1    schedule 10.05.2012    source источник


Ответы (1)


Естественный способ сделать это — запечатать модуль на сайте определения, а не на сайте использования. Тогда вам просто нужно выразить разделение типов один раз:

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
person Andreas Rossberg    schedule 11.05.2012
comment
не знал, что можно поместить модуль в другой модуль с таким же именем; противный - person codablank1; 11.05.2012