由函子构建的两个模块之间的类型关系

发布于 2025-01-01 16:44:28 字数 2033 浏览 5 评论 0原文

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

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: AREAMMMAreaMmm,因为这确保我这两个模块受到这两个签名的约束。有人可以帮忙吗?

I have defined several signatures and modules as follows:

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

And two functors:

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

And applied functors with some modules:

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

The compilation works fine on this piece of code. However, if I change the last part to

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

the compilation stops at the last line, and gives me:

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

I really want to add : AMATRIX to AMatrix and : AREAMMM to AreaMmm, because that ensures me that these two modules are constrained with these two signatures. Could anyone help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雪落纷纷 2025-01-08 16:44:28

我仍然不知道你想要实现什么,但如果你的目标是在模块之间实现某种继承(正如你在之前的一些线程标题中所说),你可能需要使用递归模块。

例如,您首先定义模块层次结构:这里 S 是初始模块签名,可以通过 S1S2 扩展:

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

然后,您创建具体的实现,它准确定义了 'a t,并实现了 S1S2 所需的所有函数:

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 抽象出来通过使用正确的签名来限制实施。您在这里需要递归模块(请注意 rec 关键字):

module rec I : S = Concrete
and I2 : S2 with type 'a t = 'a I.t = Concrete
and I1 : S1 with type 'a t = 'a I.t = Concrete

您可以测试您的结果:

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

它按预期返回 0

I have still no idea of what you try to achieve, but if your goal is to implement some kind of inheritance between you modules (as you said in some previous thread title), you may need to use recursive modules.

So for instance, you start by defining your module hierarchy: here S is the initial module signature, which can extended by S1 and 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

Then, you create your concrete implementation, which define exactly what is 'a t, and which implements all the functions needed by both S1 and S2:

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

Then, you abstract the type 'a t away by constraining the implementation with the right signatures. You need recursive modules here (note the rec keyword):

module rec I : S = Concrete
and I2 : S2 with type 'a t = 'a I.t = Concrete
and I1 : S1 with type 'a t = 'a I.t = Concrete

And you can test your result:

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

which returns 0 as expected.

猥琐帝 2025-01-08 16:44:28

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

正如我之前所解释的,如果您断言 module AMatrix : AMATRIX ,那么您将丢弃 AMATRIX< 中未包含的有关 AMatrix 内容的任何其他信息/代码>。特别是,由于 AMATRIX 没有提及 AMatrix.Mmm.tAreaMmm.Mmm.t 相同,因此该信息会丢失并且该代码无法编译。

你应该断言的是:

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

Your application needs to know that AMatrix.Mmm.t is the same as AreaMmm.Mmm.t, because otherwise you will not be able to use values created by one module in functions provided by the other module.

As I previously explained, if you assert that module AMatrix : AMATRIX then you are throwing away any additional information about the contents of AMatrix that is not contained in AMATRIX. In particular, since AMATRIX does not mention that AMatrix.Mmm.t is the same as AreaMmm.Mmm.t, that information is lost and the code does not compile.

What you should assert instead is that:

module AMatrix : AMATRIX 
  with module Mmm = MmmArray 
   and module Matrix = MatrixArray
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文