Соотношение типов между двумя модулями, построенными на функторах - PullRequest
1 голос
/ 01 февраля 2012

Я определил несколько подписей и модулей следующим образом:

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, потому что это гарантирует мне, что эти два модуля ограничены этими двумя сигнатурами. Может ли кто-нибудь помочь?

Ответы [ 2 ]

3 голосов
/ 01 февраля 2012

Я до сих пор не знаю, чего вы пытаетесь достичь, но если ваша цель - реализовать какое-то наследование между вашими модулями (как вы сказали в заголовке какого-то предыдущего потока), вам может понадобиться использовать рекурсивные модули.

Так, например, вы начинаете с определения иерархии модулей: здесь 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 голос
/ 01 февраля 2012

Вашему приложению необходимо , чтобы знать, что 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
...