Types 由函子构造的两个模之间的类型关系

Types 由函子构造的两个模之间的类型关系,types,module,ocaml,functor,Types,Module,Ocaml,Functor,我定义了几个签名和模块,如下所示: module type MATRIX = sig type 'a t val init: 'a -> 'a t end module type MMM = sig type 'a t end module type AMATRIX = sig include MATRIX module Mmm : MMM module Matrix: MATRIX val mmm_of_amatrix: 'a t -> int -&

我定义了几个签名和模块,如下所示:

module type MATRIX =
sig
  type 'a t
  val init: 'a -> 'a t
end

module type MMM =
sig
  type 'a t
end

module type AMATRIX =
sig
  include MATRIX
  module Mmm : MMM
  module Matrix: MATRIX
  val mmm_of_amatrix: 'a t -> int -> int -> 'a Mmm.t
end

module type AREAMMM =
sig
  type t
  module Mmm: MMM
  val make: int Mmm.t -> t
end

module MatrixArray: MATRIX =
struct
  type 'a t = 'a array array
  let init (e: 'a) : 'a t = failwith "to do"
end

module MmmArray: MMM =
struct
  type 'a t = 'a array array
end
和两个函子:

module AMatrixFun: functor (Mmm: MMM) -> functor (Matrix: MATRIX) -> AMATRIX
  with
    module Mmm = Mmm
  and
    module Matrix = Matrix =
      functor (Mmm: MMM) -> functor (Matrix: MATRIX) ->
    struct
      include MatrixArray
      module Mmm = Mmm
      module Matrix = Matrix
      let mmm_of_amatrix (m: 'a t) (nr_i: int) (nc_i: int) : 'a Mmm.t = failwith "to do"
    end

module AreaMmmFun : functor (Mmm: MMM) -> AREAMMM
  with module Mmm = Mmm =
    functor (Mmm: MMM) ->
  struct
    type t
    module Mmm = Mmm
    let make (x: int Mmm.t) : t = failwith "to do"
  end
和带有某些模的应用函子:

module AMatrix  = AMatrixFun(MmmArray)(MatrixArray)
module AreaMmm  = AreaMmmFun(MmmArray)

let a = AMatrix.mmm_of_amatrix (AMatrix.init 5) 0 0
let b = AreaMmm.make a
编译在这段代码上运行良好。但是,如果我将最后一部分更改为

module AMatrix : AMATRIX = AMatrixFun(MmmArray)(MatrixArray)
module AreaMmm : AREAMMM = AreaMmmFun(MmmArray)

let a = AMatrix.mmm_of_amatrix (AMatrix.init 5) 0 0
let b = AreaMmm.make a
编译在最后一行停止,并给出:

File "lib/tools.ml", line 69, characters 21-22:
Error: This expression has type int AMatrix.Mmm.t
       but an expression was expected of type int AreaMmm.Mmm.t

我真的想将
:AMATRIX
添加到
AMATRIX
中,并将
:AREAMMM
添加到
AREAMMM
,因为这样可以确保这两个模块受这两个签名的约束。有人能帮忙吗?

我仍然不知道您试图实现什么,但是如果您的目标是在模块之间实现某种类型的继承(正如您在前面的某个线程标题中所说的),您可能需要使用递归模块

例如,您可以从定义模块层次结构开始:这里
S
是初始模块签名,可以通过
S1
S2
进行扩展:

module type S = sig
  type 'a t
end

module type S1 = sig
  include S
  val f: 'a -> 'a t
end

module type S2 = sig
  include S
  val g: 'a t -> 'a
end
module Concrete = struct
  type 'a t = 'a array
  let f a = [| a |] (* fill with the right contents *)
  let g a = a.(0)   (* fill with the right contents *)
end
然后,创建具体的实现,它准确地定义了什么是
'a t
,并实现了
S1
S2
所需的所有功能:

module type S = sig
  type 'a t
end

module type S1 = sig
  include S
  val f: 'a -> 'a t
end

module type S2 = sig
  include S
  val g: 'a t -> 'a
end
module Concrete = struct
  type 'a t = 'a array
  let f a = [| a |] (* fill with the right contents *)
  let g a = a.(0)   (* fill with the right contents *)
end
然后,通过使用正确的签名约束实现,抽象出类型
'at
。这里需要递归模块(注意
rec
关键字):

您可以测试您的结果:

let a = I2.g (I1.f 0)

它会按预期返回
0

我仍然不知道您试图实现什么,但是如果您的目标是在模块之间实现某种类型的继承(如您在前面的某个线程标题中所述),您可能需要使用递归模块

例如,您可以从定义模块层次结构开始:这里
S
是初始模块签名,可以通过
S1
S2
进行扩展:

module type S = sig
  type 'a t
end

module type S1 = sig
  include S
  val f: 'a -> 'a t
end

module type S2 = sig
  include S
  val g: 'a t -> 'a
end
module Concrete = struct
  type 'a t = 'a array
  let f a = [| a |] (* fill with the right contents *)
  let g a = a.(0)   (* fill with the right contents *)
end
然后,创建具体的实现,它准确地定义了什么是
'a t
,并实现了
S1
S2
所需的所有功能:

module type S = sig
  type 'a t
end

module type S1 = sig
  include S
  val f: 'a -> 'a t
end

module type S2 = sig
  include S
  val g: 'a t -> 'a
end
module Concrete = struct
  type 'a t = 'a array
  let f a = [| a |] (* fill with the right contents *)
  let g a = a.(0)   (* fill with the right contents *)
end
然后,通过使用正确的签名约束实现,抽象出类型
'at
。这里需要递归模块(注意
rec
关键字):

您可以测试您的结果:

let a = I2.g (I1.f 0)
它按预期返回
0

您的应用程序需要知道
AMatrix.Mmm.t
AreaMmm.Mmm.t
相同,因为否则您将无法在另一个模块提供的函数中使用一个模块创建的值

如前所述,如果您断言
module AMatrix:AMatrix
,则您将丢弃
AMatrix
中未包含的有关
AMatrix
内容的任何附加信息。特别是,由于
AMATRIX
没有提到
AMATRIX.Mmm.t
AreaMmm.Mmm.t
相同,因此信息丢失,代码无法编译

你应该强调的是:

module AMatrix : AMATRIX 
  with module Mmm = MmmArray 
   and module Matrix = MatrixArray
您的应用程序需要知道
AMatrix.Mmm.t
AreaMmm.Mmm.t
相同,因为否则您将无法在另一个模块提供的函数中使用一个模块创建的值

如前所述,如果您断言
module AMatrix:AMatrix
,则您将丢弃
AMatrix
中未包含的有关
AMatrix
内容的任何附加信息。特别是,由于
AMATRIX
没有提到
AMATRIX.Mmm.t
AreaMmm.Mmm.t
相同,因此信息丢失,代码无法编译

你应该强调的是:

module AMatrix : AMATRIX 
  with module Mmm = MmmArray 
   and module Matrix = MatrixArray

再一次,和另一个线程中的问题一样:你想解决什么问题。请使用文字而不是代码。为了做一些琐碎的事情,我觉得你的代码太复杂了,所以如果你想得到一些帮助,请试着解释清楚你的问题是什么。好吧,我的代码的目的真的不是琐碎的,很难像这样解释它的具体含义。。。所以实现看起来很复杂是正常的。。。但是我认为代码的技术问题对于熟悉函子和模块的人来说是可以理解的……同样,在另一个线程中,同样的问题是:您试图解决什么问题。请使用文字而不是代码。为了做一些琐碎的事情,我觉得你的代码太复杂了,所以如果你想得到一些帮助,请试着解释清楚你的问题是什么。好吧,我的代码的目的真的不是琐碎的,很难像这样解释它的具体含义。。。所以实现看起来很复杂是正常的。。。但是我认为代码的技术问题对于熟悉函子和模的人来说是可以理解的…谢谢你的回答,如果我想强制输入
I1
I2
int-array
?我已将
中的
类型“at=”a数组
更改为
'a t=int数组
,但它不起作用…您不能直接这样做,因为
I1
满足签名
S1
'ai1.t
(其中
t
是抽象的)不能与
int数组
统一。但是,如果您愿意,您可以定义别名
type tt=int I1.t
并在签名中使用别名
tt
,但不能用
array
替换
I1.t
,因为这会破坏抽象:如果其他人使用列表等实现了
S
的具体实现呢?谢谢您的回答,如果我想将
I1
I2
中的类型强制为
int-array
,该怎么办?我已将
中的
类型“at=”a数组
更改为
'a t=int数组
,但它不起作用…您不能直接这样做,因为
I1
满足签名
S1
<代码>'a I1.t
(其中
t