我有以下模块类型:
module type Element = sig
type t
type mystruct = {x: int; y: int}
val (<) : t -> t -> bool
val string_of_element : t -> string
(* val (>) : t -> t -> bool = not (<) *)
end
如您所见,我希望类型
t
是通用的,但我希望 mystruct
具有特定的结构。问题是,当我创建一个模块 MyInteger
时,“实现”模块 Element
如下:
module MyInteger = struct
type t = int
let (<) a b = a < b
let string_of_element = string_of_int
end
它抱怨
“mystruct”类型是必需的,但未提供
除非我在这个模块中重新定义类型 mystruct,否则它不起作用。
我不明白为什么它不使用我在模块类型中定义的类型?有什么办法可以让它做到这一点吗?
与函数 (>) 相同,如何让 Ocaml 考虑 (>) 与 (<) whatever it is?
) 相反模块类型为规格。它们不实现任何东西,既不实现函数也不实现类型。 当你写模块类型时
module type Element = sig
...
type mystruct = {x: int; y: int}
...
end
您指定每个实现都必须定义自己的
mystruct
变体,这确实不是很有用。
解决方案很可能是将共享类型定义移到模块类型规范之外:
type mystruct = {x:int; y:int}
module type Element = sig ... end
如果
mystruct
类型对 Element
模块类型规范中的其他类型有一定的依赖性,一个好的解决方案是使共享类型定义多态于依赖于实现的部分:
type 'a mystruct = { x:'a; y:int }
module type Element = struct
...
type t
type mystruct_elt = t mystruct
...
end
同样,可以使用高阶函数来定义派生函数
let make_gt (<) x y = y < x
module I = struct
let (<) = ...
let (>) = make_gt (<)
end
如果有多个派生函数,您可以使用函子来扩展基本模块实现:
module Extend(X:Base_element) = struct
let (>) x y = X.( y < x )
...
end
module Full = struct
module Core = struct ... end
include Core
include Extend(Core)
end