Search code examples
moduleocamlfunctorvariantpolymorphic-variants

Variant types as module/functor signature constraints in ocaml


I'm trying to use modules/functors to have a more generic code design. To simplify, I have two interfaces:

module type T1 = sig type t end;;
module type T2 = sig type t end;;

and I'd like so instantiate T2.t with a variant type based on T1.t.

(* simple example, this one is accepted *)
module OK (T: T1) : (T2 with type t = T.t) = struct type t = T.t end;;
(* using a variant type, this one is rejected *)
module KO (T: T1) : (T2 with type t = X | Y of T.t) = struct
    type t = X | Y of T.t
end

In the latter, I get the following errors:

Unbound module X
Syntax error inside `module' after unclosed (, expected `.'

However if I use polymorphic variants, it seems to be accepted:

module OK2 (T: T1) : (T2 with type t = [ `X | `Y of T.t]) = struct
    type t = [ `X | `Y of T.t ]
end

but I clearly don't understand why. What is the correct way to use such constraints with variants ?

PS: note that this one is also rejected

module OK2 (T: T1) : (T2 with type t = [ `X | `Y of T.t]) = struct
    type t = X | Y of T.t
end

Solution

  • At module constraint with type t = ..., you can NOT write type definitions, but type expressions.

    X | Y of T.t is a rhs of a variant type definition, therefore it is rejected as a syntax error. On the other hand, [ `X | `Y of T.t] is an type expression.

    If you are not sure about the difference between the normal variants and polymorphic variants, please check OCaml books or reference manual.

    What you want to write may be

    module type T3 = sig 
      type t'
      type t = X | Y of t'
    end
    
    module KOX (T: T1) : (T3 with type t' := T.t) = struct
      type t = X | Y of T.t
    end