# Extend mutually recursive modules

**URL:** <https://discuss.ocaml.org/t/extend-mutually-recursive-modules/6391>\
**Category:** Community\
**Created:** [September 10, 2020, 4:24pm UTC](https://discuss.ocaml.org/t/extend-mutually-recursive-modules/6391 "2020-09-10T16:24:38Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Juloo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/juloo/32/881_2.png) [@Juloo](https://discuss.ocaml.org/u/Juloo)\
**Post date:** [September 10, 2020, 4:24pm UTC](https://discuss.ocaml.org/t/extend-mutually-recursive-modules/6391/1 "2020-09-10T16:24:38Z")

</div>

Hi,

I’m trying to “extend” a set of recursive modules by adding functions to them  
while keeping equalities between types. With the code below, the compiler gives me this error:

```auto
15 | type t = Orig.X.t = Y of Y.t | Z
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This variant or record definition does not match that of type Orig.X.t
       Constructors do not match:
         Y of Orig.Y.t
       is not compatible with:
         Y of Y.t
       The types are not equal.

```

```ocaml
module Orig = struct
  module rec X : sig
    type t = Y of Y.t | Z
  end =
    X

  and Y : sig
    type item = A | B
    type t = item list
  end =
    Y
end

module rec X : sig
  type t = Orig.X.t = Y of Y.t | Z
end = struct
  type t = Orig.X.t = Y of Y.t | Z
end

and Y : sig
  type item = Orig.Y.item = A | B
  type t = item list
end = struct
  type item = Orig.Y.item = A | B
  type t = item list
end

```

The error disappear if don’t use recursive modules. Of course, in my real code, the types really are mutually recursive.  
Is this a limitation due to recursive modules ?

```ocaml
module Y : sig
  type item = Orig.Y.item = A | B
  type t = item list
end = struct
  type item = Orig.Y.item = A | B
  type t = item list
end

module X : sig
  type t = Orig.X.t = Y of Y.t | Z
end = struct
  type t = Orig.X.t = Y of Y.t | Z
end

```

The reason I have such code is because I want to apply a deriving PPX only while testing, to avoid having a dependency on a PPX.  
I’m trying to use a combination of three PPXes: `ppx_gen_rec`, `ppx_import` and `ppx_deriving.show`.  
The code above is the output of them, my code looks like this:

```ocaml
module%gen rec X : sig
  type t = [%import: Orig.X.t] [@@deriving show]
end =
  X

and Y : sig
  type item = [%import: Orig.Y.item] [@@deriving show]
  type t = [%import: Orig.Y.t] [@@deriving show]
end =
  Y

```

Suggestions about this problem are welcome too 🙂

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [September 10, 2020, 5:09pm UTC](https://discuss.ocaml.org/t/extend-mutually-recursive-modules/6391/2 "2020-09-10T17:09:15Z")

</div>

The typechecker does not expand type definition of the form `X.t` while the typing of `X` is still in progress.Typically, your example can be reduced to

```ocaml
type u = A of int
module rec X: sig
  type l = int
  type t = u = A of X.l
end = X

```

> ```ocaml
> Error: This variant or record definition does not match that of type s
> Constructors do not match:
> A of int
> is not compatible with:
> A of X.u
> The types are not equal.
> 
> ```

The solution here is to avoid going through the self-referential path `X.u`:

```ocaml
module rec X: sig
  type l = int
  type t = u = A of l
end = X

```

Concerning your issue, a first question is do you need the _extension_ to be recursive once the initial modules have been defined? Or could you use:

```ocaml
module X_extension = struct
  type t = Orig.X.t = Y of Orig.Y.t | Z
end
module Y_extension = struct
  type item = Orig.Y.item = A | B
end

```

If the extension itself is recursive, you should try to separate the initial recursive definitions from the new ones with

```ocaml
module rec X_recursive_extension : sig
  type t = Orig.X.t = Y of Orign.Y.t | Z
end = ...

```

where the definition of `t` makes it clear that it is still the same module being defined.

---

<div class="post-metadata">

**Author:** ![Juloo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/juloo/32/881_2.png) [@Juloo](https://discuss.ocaml.org/u/Juloo)\
**Post date:** [September 11, 2020, 10:20am UTC](https://discuss.ocaml.org/t/extend-mutually-recursive-modules/6391/3 "2020-09-11T10:20:45Z")

</div>

Thanks for your reply !  
I didn’t expect the typechecker to have this behavior, it’s nice to know about it 🙂

Concerning my issue, the code is generated by `ppx_import`. Tuning it (with `[@with]`) would be quite hard to maintain and will not work well with `[@@deriving show]` that I’m trying to add on top.  
The whole idea was a bit crazy, I’ll try something else.
