A functor including an inheritance of modules does

2019-07-09 08:33发布

问题:

I am still struggling with my design and implementation of modules, I have defined the following:

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

module type MMM =
sig
  type 'a t
end

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

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

module MmmArray: MMM =
struct
  type 'a t = 'a array array
end

And a functor with an inheritance of modules:

module AMatrixArrayFun: functor (Mmm: MMM) -> functor (Matrix: MATRIX) -> AMATRIX =
  functor (Mmm: MMM) ->
    functor (Matrix: MATRIX) ->
struct
  include MatrixArray
  module Mmm = Mmm
  module Matrix = Matrix

  let matrix_of_amatrix (m: 'a t) (nr_i: int) (nc_i: int) : 'a Matrix.t = failwith "to do"
end

module AMatrixArray = AMatrixArrayFun(MmmArray)(MatrixArray)

let () =  MatrixArray.print (AMatrixArray.matrix_of_amatrix (AMatrixArray.init 5) 0 0)

The compilation stop at the last line, and gives an error:

Error: This expression has type
         int AMatrixArray.Matrix.t =
           int AMatrixArrayFun(MmmArray)(MatrixArray).Matrix.t
       but an expression was expected of type 'a MatrixArray.t

So it seems that the compiler does not recognize that int AMatrixArrayFun(MmmArray)(MatrixArray).Matrix.t is actually 'a MatrixArray.t, but this is exactly what a functor is meant to do, right? Maybe it is the inheritance of modules which complicates the thing?

Could anyone help?

回答1:

You have coerced the signature of your AMatrixArrayFun functor to be:

functor (Mmm: MMM) -> functor (Matrix: MATRIX) -> AMATRIX

Writing this eliminates any type relationships between the returned modules and the Mmm and Matrix argument. OCaml is only allowed to known that it's an AMATRIX, but not that its Matrix submodule was actually the Matrix module passed as a functor argument.

You need to add this information to the functor signature :

functor (Mmm: MMM) -> functor (Matrix: MATRIX) -> 
  AMATRIX with module Mmm = Mmm and  module Matrix = Matrix