Composing Polymorphic Variants with Hidden Type Variables


I’m using polymorphic variants to model errors and allow composition and I want to manually define and compose the types.

I want to lift out the lower bound polymorphic variant into a type so it can be reused and also referenced.

let someFunc = (x: int): [> `Red] => ...

So if I define it with the hidden type variable…

type color('a) = [> `Red] as 'a;

And then do this, it doesn’t seem to be the equivalent type.

let someFunc = (x: int): color('a) => ...

And in a new composed poly var it doesn’t work (or I’m not sure what the correct syntax is):

type composed('a) = [ | color('a) | `Blue ];

I get the error

... does not expand to a polymorphic variant type.

One workaround (or maybe solution) I have is to define my types monomorphically

type color = [ | `Red];
let someFunc = (x: int): [> color] => ...
type composed = [ | color | `Blue ];

Is this the correct way to compose polymorphic variants? I’m also doing it this way (rather than just letting the compiler infer everything) because I’m defining interfaces in order to use private types in my modules (opaque types).


Yeah, this looks fine to me:

type color = [`Red];
type composed('a) = [> color | `Blue ] as 'a;

Or, your method should also work fine, e.g. returning [> composed] from a function.

type color = [`Red];
type composed('a) = [> color | `Blue ] as 'a;

For completeness, what would be the syntax for a 2nd composed?

type composed2('a) = [> composed('a) | `Green] as 'a;


You’d have to stick with the fixed polymorphic variant types everywhere until the final use site.