Type mismatch with type alias inside module type


#1

Hello,

I have the same issue like this one and couldn’t find a solution…

module A {
  type variant = 
    | FOO
    | BAR;

  let toString = (variant) =>
    switch (variant) {
    | FOO => "foo"
    | BAR => "bar"
    };
};

module B1 {
  type variant_alias = A.variant;
  let log = (alias) => Js.log(A.toString(alias));
};

module type I {
  type variant;
  let toString: variant => string;
};

module type T = {
  type variant_alias;
  let log: variant_alias => unit;
};

module B2 = (AI: I): T => {
  type variant_alias = AI.variant;
  let log = (alias) => Js.log(AI.toString(alias));
}

B1.log(A.FOO);
/*
   Print foo
*/


module C = B2(A);

C.log(A.BAR);
/*
   Type mismatch

 We've found a bug for you!

  39 │ module C = B2(A);
  40 │
  41 │ C.log(A.BAR);
  42 │ 
  43 │

  This has type:
    A.variant
  But somewhere wanted:
    C.variant_alias (defined as B2(A).variant_alias)

>>>> Finish compiling(exit: 1)
   */

Everything works well when I don’t define the module type T and signed the module B2 with module type T.

But when I add the module type I got a type mismatch between the alias inference and the type definition.

I tried to make the log parameter generic like module type T = { let log: 'a => unit }; but it doesn’t work too.

How can I achieve to pass a variant to my function’s Functor?

I’d really like to keep the module type definition because I like to keep strict definition inside the rei interface file.

Your help will be greatly appreciated.


#2

I got the answer from Reason team inside Discord.

I put it here in case someone need the answer, because it’s not documented yet, add T with variant_alias = AI.variant from OCaml with parentheses around :

module B2 = (AI: I): (T with type variant_alias = AI.variant) => {
  type variant_alias = AI.variant;
  let log = (alias) => Js.log(AI.toString(alias));
}