How to define a variant that holds a set of the variant?


#1

Hi,

I’d like to define an expression as follows.

type expr =
  | And(Belt.Set(expr))
  | Or(Belt.Set(expr))
  | Literal(string)

But to define a Belt.Set, I have to define a Belt.Id.Comparable for the expr type. But it can’t be referenced before the declaration. How can I resolve this problem?


#2

Well technically you could use recursive modules, I’m not sure it’s a great idea though, I’ve never had to actually use this concept in OCaml so it might be a smell ^^

type myExpr('identity) =
  | And(Belt.Set.t(myExpr('identity), 'identity))
  | Or(Belt.Set.t(myExpr('identity), 'identity))
  | Literal(string);

module rec MyComparable:
  Belt.Id.Comparable with type t = myExpr(MyComparable.identity) =
  Belt.Id.MakeComparable({
    type t = myExpr(MyComparable.identity);
    let cmp = (a, b) =>  {... implement the cmp function};
  });

type expr = myExpr(MyComparable.identity);

let myEmptySet = Belt.Set.make(~id=(module MyComparable));
let foo = Literal("foo");
let bar = myEmptySet->Belt.Set.add(foo));
let baz = Or(bar);

#3

Thanks tsnoblp! It worked as expected!