Расширить взаимно рекурсивные функторы - PullRequest
0 голосов
/ 26 сентября 2018

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

Я написал следующие функторы, чтобы можно было повторно использовать код во время процесса:

module type Exp = sig                                                                                                                  
  type t                                                                                                                               
end  

module type IR = sig                                                                                                                    
  type exp                                                                                                                              
  type ty =                                                                                                                             
    | Unknown                                                                                                                           
    | Typed of exp                                                                                                                      
  type exp_descr =                                                                                                                      
    | Leaf                                                                                                                              
    | Node of exp                                                                                                                       
end                                                                                                                                     

module MyIR (E: Exp) = struct                                                                                                           
  type ty =                                                                                                                             
    | Unknown                                                                                                                           
    | Typed of E.t                                                                                                                      

  type exp_descr =
    | Leaf 
    | Node of E.t

  type exp = E.t  
end       

module UntypedExp (TD: IR) : (Exp with type t = TD.exp_descr) = struct
  type t = TD.exp_descr
end                          

module TypedExp (TD: IR) : Exp = struct
  type t =        
    {
      ty : TD.ty; 
      descr : TD.exp_descr;
    }            
end

module rec UTExp : Exp = UntypedExp(UTIR)
and UTIR : IR = MyIR(UTExp)

module rec TExp : Exp = TypedExp(TIR)
and TIR : IR = MyIR(TExp)

Теперь у меня есть 2 промежуточных представления, одно из которых использует нетипизированные выражения, а другое - типизированные выражения.

Теперь я хочу написать модуль печати и хочу факторизовать код таким же образом, как я делал ранее.Ниже моя неудачная попытка, я не понимаю, как правильно расширить TExp и UTexp.В частности, я не знаю, как использовать конструктор поля, определенный в TypedExp.

module type ExpPrint = sig             
  type t  
  val string_of_t: t -> string
end              

module type IRPrint = sig
  include IR
  val string_of_ty: ty -> string
  val string_of_exp_descr: exp_descr -> string
  val string_of_exp: exp -> string
end

module MyExpPrint (R: IR) (E: ExpPrint with type t = R.exp) : (IRPrint with type exp := R.exp and type exp_descr := R.exp_descr and type ty := R.ty) = struct
  open R
  let string_of_exp = E.string_of_t
  let string_of_ty = function
    | R.Unknown -> "Unknown"
    |   Typed e -> "Typed: " ^ string_of_exp e

  let string_of_exp_descr = function
    | R.Leaf   -> "Leaf"
    |   Node e -> "Node: " ^ string_of_exp e

end

module UTExpPrint (E : module type of UTExp) (R: IRPrint with type exp = E.t) : (ExpPrint with type t := R.exp_descr) = struct
  open E
  let string_of_t = R.string_of_exp_descr
end

module TExpPrint (E : module type of TExp) (R: IRPrint with type exp = E.t) : (ExpPrint with type t := R.exp) = struct
  open E
  let string_of_t e = R.string_of_exp_descr e.TExp.descr ^ " " ^ R.string_of_ty e.ty
end

EDIT: исправляет проблемы с MyExpPrint

1 Ответ

0 голосов
/ 26 сентября 2018

Поскольку тип модуля Exp определен как

 module type Exp = sig type t end

, любое сигнатурное ограничение формы M: Exp делает M непригодным для использования, поскольку оно скрывает всю информацию о M, кроме наличия абстрактногоtype Mt Этот абстрактный тип неприменим, поскольку между этим типом и внешним миром нет функций.

Например, это определение модуля определяет тип и сразу скрывает его во внешнем мире:

module TypedExp (TD: IR) : Exp = struct
  type t =        
    {
    ty : TD.ty; 
    descr : TD.exp_descr;
   }            
end

То, что вы хотели, было просто

module TypedExp (TD: IR) = struct
  type t =        
    {
    ty : TD.ty; 
    descr : TD.exp_descr;
   }            
end

Если вы действительно хотите добавить ограничение подписи, правильным будет

module TypedExp (TD: IR): sig
  type t =        
    {
    ty : TD.ty; 
    descr : TD.exp_descr;
   }            
end
= struct
  type t =        
    {
    ty : TD.ty; 
    descr : TD.exp_descr;
   }            
end

Обратите внимание, что я не использовал Exp with type t = ... по двум причинам: во-первых, ограничение with не может определять новые типы.Во-вторых, Exp with type t = ... - это просто сложный способ написания sig type t = ... end.

Это основная проблема вашего кода: он скрывает всю информацию, которая позволяет осмысленно манипулировать определенным вами типом.

Например, после удаления ограничения подписи для результата функтора, исправления подписи в рекурсивных ограничениях модуля, упрощения подписи IRprint до

module type IRPrint = sig
  type ty
  type exp_descr
  type exp
  val string_of_ty: ty -> string
  val string_of_exp_descr: exp_descr -> string
  val string_of_exp: exp -> string
end

, тогда функтор TExpPrint можно исправитьс

module TExpPrint
    (E : module type of TExp)
    (R: IRPrint with type exp_descr = TIR.exp_descr
                 and type exp = E.t
                 and type ty = TIR.ty)
=
struct
  open E
  let string_of_t e =
    R.string_of_exp_descr e.E.descr ^ " " ^ R.string_of_ty e.ty
end

, и я ожидаю, что остальные ошибки последуют, так как становится возможным разделить правильные равенства типов.

...