Ocaml: передача типа конструктора между модулями - PullRequest
4 голосов
/ 04 января 2012

У меня есть этот тип модуля:

module type MOD =    
  sig   
    type operand
    type op
    val print : op -> string
  end;;

Реализация MOD:

module M1:MOD =
  struct
    type operand = Mem of int | Reg of int | Const of int
    type op = Add of operand * operand| Sub of operand * operand
    let print op = match op with
      | Add _ -> "Add"
      | Sub _ -> "Sub"
  end;;

Я хочу создать параметризованный модуль с типом op из первого модуляи реализовать функцию на переменных этого типа.как это:

module  ARCHI = functor (M : MOD) ->
  struct
    type op = M.op

    let execute o = match o with
      | Add (x,y) -> x + y
      | Sub (x,y) -> x - y
  end;;

Я получаю ошибку : Unbound constructor Add.Как я могу справиться с этим?

Ответы [ 2 ]

7 голосов
/ 04 января 2012

Вы объявили тип op абстрактным в MOD, а затем определили свой функтор для приема модуля M типа MOD.Таким образом, вы правильно не можете иметь доступ к реализации оп.В противном случае ваш функтор не будет делать то, о чем он заявляет, а именно: взять любой модуль типа MOD, а не только определенный вами M1.в MOD выписав полное определение типа в подписи.Тем не менее, не ясно, нужен ли вам вообще функтор здесь.

2 голосов
/ 05 января 2012

В ARCHI нет декларации Add.Конструктор Add из M должен быть записан M.Add.Кроме того, как уже заметил Ашиш Агарвал , модуль ARCHI может принимать аргумент, который не имеет конструктора Add, поскольку в сигнатуре MOD не упоминается ни один конструктор с именем Add.

Если вы хотите использовать Add в M, вы должны объявить его при объявлении M, то есть в аргументе конструктора.Один из способов сделать это - полностью указать тип op в подписи MOD:

module type MOD = sig 
    type operand
    type op = Add of operand * operand| Sub of operand * operand
    val print : op -> string
  end;;

Если вы используете подпись MOD для других целей, где тип op долженоставайтесь абстрактными, есть примечание для добавления равенства типов в сигнатуру.При первоначальном определении MOD вы можете написать

module type MOD_like_M1 =
  MOD with type op = Add of operand * operand| Sub of operand * operand
module ARCHI = functor (M : MOD_like_M1) -> …

или

module type MOD_like_M1 = MOD with type op = M1.op
module ARCHI = functor (M : MOD_like_M1) -> …

или

module type MOD_like_M1 =
  MOD with type op = Add of operand * operand| Sub of operand * operand
module ARCHI = functor (M : MOD with type op = M1.op) -> …

В любом случае, в определении ARCHI, вам нужно open M или написать M.Add.

...