Recursive Module Definition


#1

I am trying to write the following types but I am getting a compiler error.

module Statement = {
  module Block = {
    type t = {body: list(Statement.t)};
  };
  type t =
    | Block(Block.t);
};

I read about module rec and module type but I can’t understand how to apply it here. I also searched for examples in github but I didn’t find any that could help me.


#2

chenglou - 03/20/2018
can’t make recursive components

chenglou - 03/20/2018
you can definitely declare a function through let rec foo = …
then use that without jsx

From the Reason Discord


#3

I don’t know if this is what you’re trying to accomplish, but I managed to get it to type with a module type annotation.

module type S = {type t;};

module rec Statement: S = {
  module Block = {
    type t = {body: list(Statement.t)};
  };
  type t =
    | Block(Block.t);
};

#4

@malisbad
Yeah, I am looking for something that uses module rec.


#5

@rdavison, Is it possible to inline S?


#6

It hides Statement.t making impossible to create a Statement.Block for example.

module type S = {type t;};

module rec Statement: S = {
  module Block = {
    type t = {body: list(Statement.t)};
  };
  type t =
    | Block(Block.t);
};

let a: Statement.t = Statement.Block({body: []});

gives a compile error

We've found a bug for you!
OCaml preview 10:24-38

The variant constructor Statement.Block can't be found.

#7

I found the following example in ocaml in a blog post (A trick: recursive modules from recursive signatures):

module rec Layered : sig
  module Even : sig
    type t =
    | Zero
    | Succ of Layered.Odd.t
  end
  module Odd : sig
    type t =
    | Succ of Layered.Even.t
  end
end = Layered

which converted to reason is

module rec Layered: {
  module Even: {
    type t =
      | Zero
      | Succ(Layered.Odd.t);
  };
  module Odd: {
    type t =
      | Succ(Layered.Even.t);
  };
} = Layered;

It seems that I have to use module X: instead of module type X inside the rec module. :slight_smile:

Using that knowledge, I could write

module rec Statement: {
  module Body: {type t = {body: list(Statement.t)};};
  type t =
    | Body(Body.t);
} = Statement;

let a: Statement.t = Statement.Body({body: []});

Thanks guys!


How to create recursive component in ReasonReact?
#8

Woah, that’s a neat trick I didn’t know about. Thanks for sharing your solution.