module - 如何定义模块签名,其模块实现由仿函数参数化

标签 module functional-programming ocaml functor

假设我有一个由模块 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_dataget_comp_id,我需要 在模块S中指定idtypedatatype;现在想象一下,我在 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/

相关文章:

javascript - 哪些 Javascript 库对 OCaml 代码的语法高亮有很好的支持?

ocaml - 关于查找文档

Python dir() 不显示包中的所有模块

go - 将 Go 依赖模块升级到新的主要版本

functional-programming - 绘图程序

Scala: “any” 和 “all” 函数

scala - 如何使用函数式编程返回列表中的所有正数和第一个负数?

javascript - 未找到导出默认值

javascript - Typescript 2 — 使用 ES6 导入和要求?

scala - 用于 Ocaml 和其他语言的基于 Actor 的分布式并发库