OCaml模块类型中mystruct与(>)方法的实现疑问
OCaml模块类型相关问题解答
一、为什么必须重新定义mystruct?
OCaml的模块类型(module type)是一份严格的接口契约,实现该类型的模块必须完全覆盖契约中的所有声明——包括所有类型定义,哪怕签名里的类型已经有明确的结构。
你的Element模块类型里声明了type mystruct = {x: int; y: int},这意味着任何符合Element类型的模块都必须显式提供这个类型的定义,OCaml不会自动将签名里的类型定义“注入”到实现模块中。
如果想避免在每个实现模块里重复定义mystruct,可以把它抽离为独立单元复用:
module type MyStruct = sig type t = {x: int; y: int} end module MyStructImpl : MyStruct = struct type t = {x: int; y: int} end module type Element = sig type t include MyStruct val (<) : t -> t -> bool val string_of_element : t -> string end module MyInteger : Element = struct type t = int include MyStructImpl let (<) a b = a < b let string_of_element = string_of_int end
二、如何让(>)自动成为(<)的取反实现?
模块签名仅用于声明接口,不能包含具体实现逻辑,因此不能直接写val (>) : t -> t -> bool = not (<)。有两种常用解决方式:
方案1:通过基础模块复用(>)实现
定义一个通用基础模块,让其他模块继承它的(>)逻辑:
module type Element = sig type t type mystruct = {x: int; y: int} val (<) : t -> t -> bool val (>) : t -> t -> bool val string_of_element : t -> string end module ElementBase (E : sig type t val (<) : t -> t -> bool end) = struct let (>) a b = not (E.(a < b)) end module MyInteger : Element = struct type t = int type mystruct = {x: int; y: int} let (<) a b = a < b include ElementBase(struct type t = int let (<) = (<) end) let string_of_element = string_of_int end
方案2:用Functor统一生成带(>)的模块
如果有多个类似MyInteger的模块,可以用Functor自动添加(>)的取反实现:
module type ElementCore = sig type t type mystruct = {x: int; y: int} val (<) : t -> t -> bool val string_of_element : t -> string end module type Element = sig include ElementCore val (>) : t -> t -> bool end module MakeElement (Core : ElementCore) : Element = struct include Core let (>) a b = not (a < b) end module MyIntegerCore : ElementCore = struct type t = int type mystruct = {x: int; y: int} let (<) a b = a < b let string_of_element = string_of_int end module MyInteger = MakeElement(MyIntegerCore)
内容的提问来源于stack exchange,提问作者Abdelghani
相关产品推荐
相关产品推荐

