Polymorphic variants and constructors

Viewed 71

I'm just wondering how flexible OCaml's polymorphic variants are.

I know I can use the same constructor across different types but what is meant by the same constructor?

I know its fine to use `Nil here.

type 'a vlist = [`Nil | `Cons of 'a * 'a vlist]

type 'a btree = [`Nil | `Node of ('a * 'a btree * 'a btree)]

But is it ever OK to use `Node like this?

type 'a vlist = [`Nil | `Node of 'a * 'a vlist]

type 'a btree = [`Nil | `Node of ('a * 'a btree * 'a btree)]
1 Answers

You can have the vlist and btree definitions simultaneously. Values built from polymorphic variants are typed according to their structure, so there is no conflict between different uses of the same constructors.

Here is a session showing some possibilities that I tried:

# type 'a vlist = [`Nil | `Node of 'a * 'a vlist];;
type 'a vlist = [ `Nil | `Node of 'a * 'a vlist ]
# type 'a btree = [`Nil | `Node of ('a * 'a btree * 'a btree)]  ;;
type 'a btree = [ `Nil | `Node of 'a * 'a btree * 'a btree ]
# let x : int vlist = `Node (3, `Nil);;
val x : int vlist = `Node (3, `Nil)
# let y : int btree = `Node (4, `Nil, `Nil);;
val y : int btree = `Node (4, `Nil, `Nil)
# let z = `Node (7, `Nil, `Nil, `Nil);;
val z : [> `Node of int * [> `Nil ] * [> `Nil ] * [> `Nil ] ] =
    `Node (7, `Nil, `Nil, `Nil)

The point of the z example is to show that there's no need to declare the type ahead of time. You can build pretty much any structure you like with polymorphic variants, and the type will be inferred from the structure. Different uses of the same constructor don't have to agree in arity or in the types of the constituents.

(On the other hand I'm not an expert on polymorphic variants; I use them sparingly because they lead to large type expressions and complicated error messages.)

Related