Определить функции над 2 параллельными модулями, построенными на функторах - PullRequest
0 голосов
/ 01 февраля 2012

Я все еще борюсь с моим дизайном и реализацией, думал, что он прогрессирует ...

Сначала я определил 2 базовые сигнатуры и 2 модуля:

module type MATRIX = sig type 'a t end    
module MatrixArray: MATRIX = struct
  type 'a t = 'a array array
end

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

Затем я определил3 подписи, 3 функтора и их применение с помощью основных модулей, указанных выше:

module type AMATRIX = sig
  include MATRIX
  module Mmm : MMM
  module Matrix: MATRIX
  val g: 'a Mmm.t -> 'a Matrix.t -> 'a Mmm.t * 'a Matrix.t
end
module AMatrixFun (Mmm: MMM) (Matrix: MATRIX) : AMATRIX with module Mmm = Mmm and module Matrix = Matrix = struct
  include MatrixArray
  module Mmm = Mmm
  module Matrix = Matrix
  let g (mmm: 'a Mmm.t) (dbm: 'a Matrix.t) : 'a Mmm.t * 'a Matrix.t = failwith "to do"
end
module AMatrixArray  = AMatrixFun(MmmArray)(MatrixArray)

module type VIDBM = sig
  module Matrix: MATRIX
  type t = | Dtop | Dbot | D of int Matrix.t
end
module ViDbmFun (Matrix: MATRIX) : VIDBM with module Matrix = Matrix = struct
  module Matrix = Matrix
  type t = | Dtop | Dbot | D of int Matrix.t
end
module ViDbmArray = ViDbmFun(MatrixArray)

module type AREAMMM = sig
  module Mmm: MMM
  type t = | Mtop | Mbot | M of int Mmm.t
end
module AreaMmmFun (Mmm: MMM) : AREAMMM with module Mmm = Mmm = struct
  module Mmm = Mmm
  type t = | Mtop | Mbot | M of int Mmm.t
  let f (am: t) (vd: ViDbmArray.t) : t * ViDbmArray.t =
    let (M mmm), (ViDbmArray.D dbm) = am, vd in
    (AMatrixArray.g mmm dbm);
    failwith "to do"
end
module AreaMmmArray  = AreaMmmFun(MmmArray)

На самом деле мне нужно определить функцию f: AreaMmmArray.t -> ViDbmArray.t -> AreaMmmArray.t * ViDbmArray.t, для которой требуется другая функция g: 'a Mmm.t -> 'a Matrix.t -> 'a Mmm.t * 'a Matrix.t.Поскольку речь идет о типах нескольких параллельных модулей, мой главный вопрос в том, в каких модулях я должен их определять.

В приведенном выше коде я попробовал реализовать f в ViDbmFun и g в AMatrixFun.Компиляция останавливается на (AMatrixArray.g mmm dbm); и дает мне:

Error: This expression has type int Mmm.t = int Mmm.t
       but an expression was expected of type
         'a AMatrixArray.Mmm.t = 'a MmmArray.t

Я думаю, что ошибка разумна, потому что int Mmm.t в AreaMmmFun может быть чем-то отличным от MmmArray.t, принудительно введенным в AMatrixArray ..Есть ли способ обойти это?

Опять же, я думаю, что главный вопрос в том, где определить f и g, кто-нибудь может помочь?

Ответы [ 2 ]

1 голос
/ 02 февраля 2012

Я не уверен, чего вы пытаетесь достичь, но, как вы говорите, ссылка на конкретный экземпляр AMatrix в функторе AreaMmm не имеет смысла.Есть только два решения: вам нужно либо параметризировать функтор AreaMmm над экземпляром AMATRIX with module Mmm = Mmm, либо вы должны создать подходящий функтор внутри функтора.

0 голосов
/ 02 февраля 2012

Я бы сказал, что вы на самом деле не на правильном уровне определения. Matrix и Mmm независимы и объединены в матрицу AMatrix. Here you try to define a function that speaks about both and Ммм in a FooMmmFun functor, which only knows about Ммм , not Матрица ; using the particular instance MatrixArray` - не решение ошибка типа при попытке сделать это.

Вы должны определить f на уровне, который знает как Matrix (или ViDbm), так и Mmm (или AreaMmm). Вот мое предложение, чтобы добавить к вашему коду после объявления подписи AREAMMM. Он в основном определяет слой с функторизацией для AMatrix, как вы сделали для Matrix и MMM.

(* does not speak about `f` as no `Matrix` is available *)
module AreaMmmFun (Mmm: MMM) : AREAMMM with module Mmm = Mmm = struct
  module Mmm = Mmm
  type t = | Mtop | Mbot | M of int Mmm.t
end
module AreaMmmArray  = AreaMmmFun(MmmArray)

(* a functor over `AMatrix`, that knows both `Matrix` and `Mmm`,
   so we can define `f` here. I don't know which signature you want. *)
module AMatrixFun (AMatrix : AMATRIX)
= struct
  module ViDbm = ViDbmFun(AMatrix.Matrix)
  module AreaMmm = AreaMmmFun(AMatrix.Mmm)

  let f (am: AreaMmm.t) (vd: ViDbm.t) : AreaMmm.t * ViDbm.t =
    let (AreaMmm.M mmm), (ViDbm.D dbm) = am, vd in
    (AMatrix.g mmm dbm);
    failwith "to do"
end

module AmatrixFooArray = AMatrixFun(AMatrixArray)

PS: вы можете определить параметрический тип для типов, закрытых сверху / снизу, чтобы избежать дублирования имен конструкторов. Снаружи любого модуля:

type 'a order = Top | Bot | D of 'a

Затем вы можете определить VIDBM.t как int Matrix.t order и AREAMMM.t как int Mmm.t order вместо двух несовместимых типов и семейств конструкторов (Mtop, Dtop ...).

...