此问题的更清晰版本已发布here。
我已经定义了一个签名和两个模块,如下所示。定义2个模块的原因是我可以根据上下文使用MatrixArray
或MatrixList
...
module type MATRIX =
sig
type 'a t
...
end
module MatrixArray =
(struct
type 'a t = 'a array array
...
end: MATRIX)
module MatrixList =
(struct
type 'a t = 'a list list
...
end: MATRIX)
然后我定义了另一个签名和另外2个与MATRIX
,MatrixArray
和MatrixList
相关的模块:
module type PM =
sig
type 'a t
(* val of_matrix: 'a MatrixArray.t -> 'a t *)
val of_matrix: 'a MATRIX.t -> 'a t
...
end
module PmArray =
(struct
type 'a t = 'a array array
let of_matrix (m: 'a MatrixArray.t) : 'a t =
...
end: PM)
module PmList =
(struct
type 'a t = 'a list list
let of_matrix (m: 'a MatrixList.t) : 'a t =
...
end: PM)
在签名PM
中,我可以定义val of_matrix: 'a MatrixArray.t -> 'a t
,但我无法定义val of_matrix: 'a MATRIX.t -> 'a t
(Error: Unbound module MATRIX
)。所以我猜MATRIX.t
总是非法......
我真正想要实现的是......在签名级别of_matrix: 'a MATRIX.t -> 'a PM.t
上,但在模块PmArray
,of_matrix: 'a MatrixArray.t -> 'a PmArray.t
的级别上;在模块级PmList
,of_matrix: 'a MatrixList.t -> 'a PmList.t
。
我不知道是否必须定义额外的模块或仿函数来实现这种结构......希望我的关注得到很好的描述,有人可以帮忙吗?
EDIT1:
我只是意识到of_matrix
的名称可能会产生误导,例如,它会被称为f
。它只代表'a MatrixArray.t -> 'a PmArray.t
或'a MatrixList.t -> 'a PmList.t
类型的函数,其实现内部可能很复杂。而且我想提出类型'a MATRIX.t -> 'a PM.t
,遗憾的是不允许这样做。
EDIT2:
我会调用PM
作为实例TRIANGLE
,并调用PmArray
TriagleArray
(表示由数组数组表示的三角形),并调用PmList
TriangleList
(表示由列表列表表示的三角形)。给定矩阵m
,函数f (m: a MatrixArray.t) : 'a TriangleArray.t
使其左上半部分由对角线分开。
在目前阶段,像: 'a MatrixArray.t -> 'a TriangleList.t
这样的函数并不是必需的,虽然以后没有理由将它们排除在外......我在模块级别真正需要的是: a MatrixArray.t -> 'a TriangleArray.t
和{{1我希望对它们有一个共同的签名/约束:: a MatrixList.t -> 'a TriangleList.t
某处。
答案 0 :(得分:1)
主要问题似乎是'a MATRIX.t
不是一个类型,所以它不能用于构建新的函数类型。这意味着声明val 'a MATRIX.t -> 'a t
不是有效的函数定义。
类型签名仅定义类型约束。在大多数情况下,您不需要类型签名,因为它们很容易被模块本身所感染。使用类型签名的主要原因是您计划稍后对代码进行编译。在这种情况下,您需要定义要用作输入和输出到仿函数的类型签名。所有符合该签名的模块都将被允许,无论它们是否实际上属于上述类型。 OCaml在模块和对象层面上确实使用了Duck Typing。
因此,简单的解决方案是完全摆脱模块签名PM。这也将减少没有真正语义的代码量。如果你真的需要模块签名(或者当前正在玩模块)。
以下是您问题的一种可能解决方案:
module type MATRIX =
sig
type 'a t
end
module MatrixArray =
(struct
type 'a t = 'a array array
type 'a b = 'a
end: MATRIX)
module MatrixList =
(struct
type 'a t = 'a list list
end: MATRIX)
module type PM =
sig
type 'a t
end
module Pm = functor ( M: MATRIX) ->
(struct
type 'a t = 'a M.t
end: PM with type 'a t = 'a M.t )
module PmArray = Pm(MatrixArray)
module PmList = Pm(MatrixList)
并不是说with子句在参数类型'a MATRIX.t
之间引入了一个类型等价(实际上不是一个类型,但是一旦实例化了仿函数就变为一个),结果类型'a PM.t
(同样不是真的一种)。因此,在实例化仿函数时,必要的等式将保持不变,并且不需要of_matrix
函数。
然而,可能有其他解决方案更适合您的需求,例如只删除签名并仅使用模块。