Types 签名中用于另一签名的类型
这个问题的更清晰版本已经发布。Types 签名中用于另一签名的类型,types,module,ocaml,signature,Types,Module,Ocaml,Signature,这个问题的更清晰版本已经发布。 我定义了一个签名和两个模块,如下所示。定义两个模块的原因是我可以根据上下文使用MatrixArray或MatrixList module type MATRIX = sig type 'a t ... end module MatrixArray = (struct type 'a t = 'a array array ... end: MATRIX) module MatrixList = (struct
我定义了一个签名和两个模块,如下所示。定义两个模块的原因是我可以根据上下文使用
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)
然后我定义了另一个签名和另外两个与矩阵
、矩阵阵列
和矩阵列表
相关的模块:
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:'a MatrixArray.t->'a t
,但我不能定义_矩阵的val:'a matrix.t->'a t
(错误:未绑定模块矩阵
)。所以我猜MATRIX.t
总是非法的
我真正想知道的是。。。在签名级别上,的_矩阵:'a matrix.t->'a PM.t
,但在模块PmArray
级别上,的_矩阵:'a MatrixArray.t->'a PmArray.t
;在模块PmList
的级别上,矩阵的,'a MatrixList.t->'a PmList.t
我不知道我是否需要定义额外的模块或函子来实现这个结构。。。希望我的担忧描述得很好,有人能帮忙吗
Edit1:
我刚刚意识到,矩阵的名称可能有误导性,例如,它会被称为f
。它只表示类型为'MatrixArray.t->'PmArray.t
或'MatrixList.t->'PmList.t
的函数,其内部实现可能比较复杂。我想把它的类型'a MATRIX.t->'a PM.t
,不幸的是这是不允许的
Edit2:
我会调用PM
例如TRIANGLE
,调用PmArray
triaglearay
(表示由数组数组表示的三角形),并调用PmList
TriangleList
(表示由列表表示的三角形)。给定一个矩阵m
,函数f(m:a MatrixArray.t):'a TriangleArray.t
将其左上半部分用对角线隔开
在当前阶段,像:'a MatrixArray.t->'和TriangleList.t
这样的函数实际上是不必要的,尽管以后没有理由排除它们。。。在模块级,我真正需要的是:MatrixArray.t->'一个TriangleArray.t
和:MatrixList.t->'一个TriangleList.t
,我只想给他们一个通用的签名/约束:'一个MATRIX.t->'一个TRIANGLE.t
,主要的问题似乎是,矩阵.t
不是一种类型,因此不能用于构建新的函数类型。这意味着声明val'a MATRIX.t->'a t
不是有效的函数定义
类型签名仅定义类型上的约束。在大多数情况下,您不需要类型签名,因为它们可以很容易地从模块本身推断出来。使用类型签名的主要原因是您是否计划稍后对代码进行函数化。在这种情况下,需要定义要用作functor输入和输出的类型签名。所有符合该签名的模块都将被允许,无论它们是否实际属于上述类型。OCaml实际上是在模块和对象级别上使用的
因此,简单的解决方案是完全去掉模块签名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子句并不是在参数type'a MATRIX.t
(不是真正的类型,但一旦函子实例化,就会变成一个类型)和结果type'a PM.t
(也不是真正的类型)之间引入类型等价性。因此,当实例化函子时,必要的等式将保持不变,并且不需要你的of_matrix
函数
但是,可能还有其他更适合您需要的解决方案,例如仅删除签名并仅使用模块。我不确定您的设计想要实现什么。签名的定义只对实现该签名的模块定义了一个约束,而没有定义类型。因此,函数类型
val of_matrix:'a matrix.t->'a t
无效。但是,我不确定您试图实现什么,因此我不确定您的问题的正确解决方案是什么。还要注意,您当前的设计可能会在以后失败,因为MatrixArray.t
在MatrixArray
中是抽象的。因此,您将无法在矩阵的中使用它的内部实现。这也可以通过使用函子来解决。定义2个模块的原因是我可以根据上下文使用MatrixArray或MatrixList。。。我看不到你的第二个评论…问题更为关键,你为什么需要签名,为什么要把你的东西分成矩阵和Pm部分,尽管这些似乎都属于您提供的代码。关于其他注释:当您将模块MatrixArray
定义为签名MatrixArray
时,类型'a MatrixArray.t
将变得抽象。因此,像int-array=int-MatrixArray.t
这样的简单等式将不再适用于模块之外。这意味着您必须将'a PmArray.t
和'a MatrixArray
视为完全不同的类型。例如,实现let of_matrix(m:'a MatrixArray.t):'a t=m
将不起作用,因为这里'a t
和a MatrixArray.t
引用的是不同的类型(尽管它们具有相同的实现)。感谢您的评论。。。请查看我的Edit1