Неверно, что полиморфные варианты всегда менее эффективны. Используя пример Мартина:
type base = [`String of string | `Int of int]
type t1 = [base | `Bool of bool | `List of t1 list]
type t2 = [base | `Other]
let simplify (x:t1):t2 = match x with
| #base as b -> b
| `Bool _ | `List _ -> `Other
Чтобы сделать это с помощью стандартных вариантов требует двух различных типов и полный перекодировки, с вариантами полиморфный базовый случай физически инвариантом.Эта функция действительно вступает в свои правах при использовании открытой рекурсии для термина переписывания:
type leaf = [`String of string | `Int of int]
type 'b base = [leaf | `List of 'b list]
type t1 = [t1 base | `Bool of bool ]
type t2 = [t2 base | `Other]
let rec simplify (x:t1):t2 = match x with
| #leaf as x -> x
| `List t -> `List (List.map simplify t)
| `Bool _ -> `Other
и преимущество еще больше, когда переписывание функция также учтена при открытой рекурсии.
К сожалению, вывод типа Hindley-Milner от Ocaml не достаточно силен, чтобы делать такие вещи без явного ввода текста, что требует тщательной факторизации типов, что в свою очередь затрудняет протопипирование. Кроме того, иногда требуются явные принуждения.
Большой недостаток этой техники заключается в том, что для терминов с несколькими параметрами в ближайшее время заканчивается довольно запутанный комбинаторный взрыв типов, и, в конце концов, легче отказаться от статического принуждения и использовать тип кухонной раковины с подстановочными знаками и исключениями (например, динамическая типизация).
Я думаю, что предпочтительным названием является «открытые варианты». – ygrek
«открытый вариант» явно проще интуитивно понять, затем «полиморфный вариант». –
Я думаю, что «открытый вариант» более точно относится к типам «exn». –