Модули OCaml: перенос (взаимосвязанных) типов из разных модулей в новый модуль

Проблема

Одна проблема, с которой я столкнулся, - это объединение типов и значений двух модулей в новый комбинированный модуль. Приведу пример. В настоящее время у меня есть две следующие сигнатуры типов

module type Ordered =
 sig
  type t (* the type of elements which have an order *)
  val eq : t * t -> bool
  val lt : t * t -> bool
  val leq : t * t -> bool
 end

module type Stack =
 sig
  exception Empty 
  type 'a t (* the type of polymorphic stacks *)

  val empty  : 'a t
  val isEmpty : 'a t -> bool

  val cons  : 'a * 'a t -> 'a t
  val head  : 'a t -> 'a
  val tail  : 'a t -> 'a t
 end

, и я хотел бы создать модуль «стеков, для которых упорядочены основные элементы», т.е.

module type OrderedStack =
 sig 
  exception Empty

  type elem (* the type of the elements in the stack *)
  val eq : elem * elem -> bool
  val lt : elem * elem -> bool
  val leq : elem * elem -> bool

  type t (* the type of monomorphic stacks *)
  val empty  : t
  val isEmpty : t -> bool
  val cons  : elem * t -> t
  val head  : t -> elem
  val tail  : t -> t
 end

Здесь все хорошо и аккуратно. Но теперь я хотел бы написать функтор, который принимает модуль Ordered и модуль Stack и создает модуль OrderedStack. Что-то вроде

module My_functor (Elem : Ordered) (St : Stack): OrderedStack  = 
 struct
  exception Empty

   type elem = Elem.t
  let eq = Elem.eq
  let lt = Elem.lt
  let leq = Elem.leq

  type t = elem St.t
  let empty = St.empty
  let isEmpty = St.isEmpty
  let cons = St.cons
  let head = St.head
  let tail = St.tail
 end

Это именно то, что я хочу и правильно. Но это выглядит как ужасная трата клавиатуры.

Мой вопрос

Есть ли более компактный способ написать My_functor выше?

Что я узнал, но не смог заставить работать

Я видел директиву include , в которой я мог бы написать что-то вроде:

module my_functor (Elem : Ordered) (St : Stack): OrderedStack  = 
 struct
  include Elem
  include St
 end

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

Я также видел, что здесь может быть уместен с оператором , но я не вполне мог понять, как его следует использовать для получения желаемого эффекта . Проблема, с которой я столкнулся, заключается в том, что типы t и из двух модулей Упорядоченные и Стеки и фактически связаны. {Y y_; X (const Y & y): y_ (y) {} X (Y && y): y_ (std :: move (y)) {} }; Необходимо ли определять конструктор, подобный второму, по порядку ...

Примите во внимание следующее:

struct X
{
    Y y_;

    X(const Y & y) :y_(y) {}    
    X(Y && y) :y_(std::move(y)) {}
};

Необходимо ли определять конструктор, подобный второму, чтобы в полной мере использовать семантику перемещения? Или это будет сделано автоматически в соответствующих ситуациях?

11
задан Jonathan Leffler 29 January 2011 в 20:34
поделиться