Suppose that I want to model a simple expression type in OCaml:
type expr =
| `Int of int
| `Str of string
| `IntAdd of expr * expr
| `StrAdd of expr * expr
Is it possible to restrict expr in expr * expr to specific constructors of expr itself (i.e. I'd like IntExpr to only allow 'Int's)? I can mimic this with pattern
matching but it gets cumbersome after expr expands. Can I somehow
use OCaml's type system to achieve this?
I tried using polymorphic type upper bounds as follows:
type expr =
| `Int of int
| `Str of string
| `IntAdd of [< `Int] * [< `Int]
| `StrAdd of [< `Str] * [< `Str]
but compiler does not accept this (with message In case IntAdd of [< Int ] * ([< Int ] as 'a) the variable 'a is unbound). Is there any trick to make this work?
The given example is simple enough for polymorphic variants to suffice:
If you want more interesting features like polymorphic data structures, GADTs are necessary:
Inference and comprehensibility of error messages suffers with GADTs, so be prepared to work to overcome those difficulties if you decide to use them.