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