我已经定义了几个签名和模块如下:
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
,因为这可以确保这两个模块受这两个签名的约束。有人可以帮忙吗?
答案 0 :(得分:3)
我仍然不知道你想要实现什么,但如果你的目标是在你的模块之间实现某种继承(正如你在之前的一些主题标题中所说的那样),你可能需要使用递归模块。
例如,您首先要定义模块层次结构:此处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
然后,您创建具体的实现,它确切地定义了什么是'a t
,并实现了S1
和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
然后,通过使用正确的签名约束实现来抽象类型'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
。
答案 1 :(得分:1)
您的应用程序需要知道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