Technique for drying out associated "with type" expressions?

Hi Folks, Im building a rather elaborate, recursive construction in module functors. and I want the inner types to be visible up through the outer layers, so I am doing a lot of:

  module type Field = {
     type t
     type inner

  module type Tail = {
    include Field

  module T2 = (A: Field, B: Field) => {
     type inner = (A.t, B.t)
     type t = { inner: inner }

  module Rec = (Head: Field, Tail: Tail) => {
   type inner = (Head.t, Tail.inner)
   type t = { inner: inner }

  module T3 = (A: Field, B: Field, C: Field)
    : ( Field
         with type inner = (A.t, (B.t, C.t))
         and type t = { inner: (A.t, (B.t, C.t))
     ) => Rec(A, T2(B, C))

So if you look at the ultimate module T3. to expose those types outward I need to reproduce the types from inside the module, and duplicate inner in its own type decl and in t. One of these at one layer isnt so bad, but doing this 6 layers deep with many types gets painful. Is there a trick to sharing the types being exposed? I wish I could just say which types i wanted to expose, too. and not repeat them, but I suppose I can see the value there.


A good first step is to make a type signature for your module functor, so atleast you dont need to repeat yourself for T3, T4, T5…but could be tigher still