gpt4 book ai didi

module - OCaml 模块 : bringing (interconnected) types from different modules into a new module

转载 作者:行者123 更新时间:2023-12-02 07:01:47 30 4
gpt4 key购买 nike

问题

我遇到的一个问题是将两个模块的类型和值带入一个新的组合模块中。我举个例子。目前我有以下两种类型签名

module type Ordered =
sig
type t (* the type of elements which have an order *)
val eq : t * t -> bool
val lt : t * t -> bool
val leq : t * t -> bool
end

module type Stack =
sig
exception Empty
type 'a t (* the type of polymorphic stacks *)

val empty : 'a t
val isEmpty : 'a t -> bool

val cons : 'a * 'a t -> 'a t
val head : 'a t -> 'a
val tail : 'a t -> 'a t
end

我想创建一个“基本元素已排序的堆栈”模块,即

module type OrderedStack =
sig
exception Empty

type elem (* the type of the elements in the stack *)
val eq : elem * elem -> bool
val lt : elem * elem -> bool
val leq : elem * elem -> bool

type t (* the type of monomorphic stacks *)
val empty : t
val isEmpty : t -> bool
val cons : elem * t -> t
val head : t -> elem
val tail : t -> t
end

到目前为止,一切都很好、很整洁。但现在,我想编写一个仿函数,它接受 Ordered 模块和 Stack 模块并生成 OrderedStack 模块。类似的东西

module My_functor (Elem : Ordered) (St : Stack): OrderedStack  = 
struct
exception Empty

type elem = Elem.t
let eq = Elem.eq
let lt = Elem.lt
let leq = Elem.leq

type t = elem St.t
let empty = St.empty
let isEmpty = St.isEmpty
let cons = St.cons
let head = St.head
let tail = St.tail
end

这正是我想要的并且是正确的。但这看起来非常浪费键盘。

我的问题

是否有更紧凑的方式来编写上面的 My_functor

我发现但无法付诸实践的内容

我见过 include 指令,我可以在其中编写如下内容:

module my_functor (Elem : Ordered) (St : Stack): OrderedStack  = 
struct
include Elem
include St
end

但这有一个问题,对于我上面的两个特定模块,Ordered 和 Stack 都具有相同的 type t (尽管它们在每个模块中的含义不同)。我不想更改 OrderedStacks 的原始定义,因为它们已经在代码的许多部分中使用,但是如果您找到原始两个的替代公式让它工作的模块,那很好。

我还看到 with operator可能与此相关,但我无法完全弄清楚应该如何使用它来产生所需的效果。我面临的问题是两个模块 OrderedStacks 的类型 t'a t 和实际已连接。

有什么想法吗?

最佳答案

OrderedStack 重用有序定义,但类型略有不同(elem 而不是 t)。这是冗余的原因。

您可以直接使用此 OrderedStack 签名来重用 Ordered :

module type OrderedStack = sig
module Elem : Ordered

type t
val empty : t
val isEmpty : t -> bool
val cons : Elem.t * t -> t
val head : t -> Elem.t
val tail : t -> t
end

冗余的另一个来源是从参数类型 'a Stack.t 转移到单态 OrderedStack.t。这两种类型不能等同,根本没有可比性,所以这里需要手工翻译。

请注意,您可以将从(多态)StackOrderedStack 的移动分解为一个中间堆栈(单态)MonoStack:

module type MonoStack = sig
type elem
type t
val empty : t
val isEmpty : t -> bool
val cons : elem * t -> t
val head : t -> elem
val tail : t -> t
end

module type OrderedStack = sig
module Elem : Ordered
module Stack : MonoStack with type elem = Elem.t
end

编辑

如果您不喜欢使用子模块的额外间接性(这会增加一些语法负担),则可以包含模块而不是链接到它们。但正如您所注意到的,问题在于名称冲突。从 OCaml 3.12 开始,我们的工具集中有一个新的构造,它允许重命名签名的类型组件以避免冲突。

module type OrderedStack = sig
type elem
include Ordered with type t := elem
include MonoStack with type elem := elem
end

第二次编辑

好的,我想出了以下解决方案来引入 Stack/MonoStack 桥接器。但坦率地说,这是一种黑客行为,我认为这不是一个好主意。

module type PolyOrderedStack = sig
module Elem : Ordered
type t
type 'a const = t
module Stack : Stack with type 'a t = 'a const
end

(* 3.12 only *)
module type PolyOrderedStack = sig
type elem
include Ordered with type t := elem
type t
type 'a const = t
include Stack with type 'a t := 'a const
end

关于module - OCaml 模块 : bringing (interconnected) types from different modules into a new module,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4839252/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com