Reusing OrderedStack Ordered definitions with a slightly different type ( elem instead of t ). This is the cause of redundancy.
Instead, you can use this OrderedStack signature, which will be reused by Ordered :
module type OrderedStack = sig module Elem : Ordered type t val empty : t val isEmpty : t -> bool val cons : Elem.t * t -> t val head : t -> Elem.t val tail : t -> t end
Another source of redundancy is the fact that you are switching from the parametric type 'a Stack.t to the monomorphic OrderedStack.t . These two types cannot be identified, they are not at all comparable, so you must definitely do the translation manually.
Note that you can decompose the transition from (polymorphic) Stack to OrderedStack into one intermediate stack (monomorphic) MonoStack :
module type MonoStack = sig type elem type t val empty : t val isEmpty : t -> bool val cons : elem * t -> t val head : t -> elem val tail : t -> t end module type OrderedStack = sig module Elem : Ordered module Stack : MonoStack with type elem = Elem.t end
Edit
If you do not like the additional indirect use of submodules, which can add a syntactic burden, it is possible to include modules instead of binding them. But the problem, as you noticed, is a name conflict. Starting with OCaml 3.12, we have a new design in our toolbox that allows you to rename components such as signatures to avoid conflicts.
module type OrderedStack = sig type elem include Ordered with type t := elem include MonoStack with type elem := elem end
Second edit
Ok, I came up with the following solution to bring the Stack / MonoStack . But to be honest, it's a hack, and I don't think this is a good idea.
module type PolyOrderedStack = sig module Elem : Ordered type t type 'a const = t module Stack : Stack with type 'at = 'a const end (* 3.12 only *) module type PolyOrderedStack = sig type elem include Ordered with type t := elem type t type 'a const = t include Stack with type 'at := 'a const end
gasche
source share