Lets say I have some GADT t
:
type _ t =
| Str : string t
| Int : int t
and I want to write a function that takes some identifier (we’ll use an int
) and returns a corresponding value of t
:
let f = function
| 0 -> Some Str
| 1 -> Some Int
| _ -> None
The above function doesn’t compile for obvious reasons; the first branch concretizes the return type as string t
. Fair enough, but using locally abstract types doesn’t work either:
let f (type a) : int -> a t option = function
...
This time the compiler complains that string
and int
are not equal to type a
, which also makes sense.
This also doesn’t work with explicit polymorphism. The one case that I’ve found does work is when using first class modules:
module type Flat_t = sig
type arg
val v : arg t
end
let f = function
| 0 -> Some (module struct type t = string let v = Str end)
...
This seems redundant to me as no extra information is added in the module.
I understand why this is the case – I’m just wondering if there’s a more elegant solution to this that doesn’t require the extra indirection of wrapping the values with modules.