Предположим, у меня есть тип, состоящий из нескольких полиморфных c вариантов (ковариантно), таких как:
[> `Ok of int | `Error of string]
Предположим далее, что я хочу преобразовать это определение в некий конструктор типов и тип бетона int
. Моей первой попыткой было следующее:
type 'a error = [> `Ok of 'a | `Error of string]
Тем не менее, использование такого определения приводит к действительно странной ошибке типа с упоминанием переменной типа 'b
, которая нигде не появляется в определении.
$ ocaml
OCaml version 4.07.0
# type 'a error = [> `Ok of 'a | `Error of string ];;
Error: A type variable is unbound in this type declaration.
In type [> `Error of string | `Ok of 'a ] as 'b the variable 'b is unbound
Это 'b
является автоматически сгенерированным именем, добавление явного 'b
смещает переменную в 'c
.
$ ocaml
OCaml version 4.07.0
# type ('a, 'b) error = [> `Ok of 'a | `Error of 'b ];;
Error: A type variable is unbound in this type declaration.
In type [> `Error of 'b | `Ok of 'a ] as 'c the variable 'c is unbound
Использование инвариантной конструкции [ `Thing1 of type1 | `Thing2 of type 2 ]
, кажется, прекрасно работает в этом context.
$ ocaml
OCaml version 4.07.0
# type 'a error = [ `Ok of 'a | `Error of string ] ;;
type 'a error = [ `Error of string | `Ok of 'a ]
#
Однако явная пометка параметра type как ковариантного не спасает исходный пример.
$ ocaml
OCaml version 4.07.0
# type +'a error = [> `Ok of 'a | `Error of string];;
Error: A type variable is unbound in this type declaration.
In type [> `Error of string | `Ok of 'a ] as 'b the variable 'b is unbound
И, просто, добавление аннотации контравариантности также не работа.
$ ocaml
OCaml version 4.07.0
# type -'a error = [> `Ok of 'a | `Error of string];;
Error: A type variable is unbound in this type declaration.
In type [> `Error of string | `Ok of 'a ] as 'b the variable 'b is unbound
Попытка угадать имя, которое компилятор будет использовать для переменной несвязанного типа, и добавление его в качестве параметра слева также не работает и выдает очень странное сообщение об ошибке.
$ ocaml
OCaml version 4.07.0
# type ('a, 'b) string = [> `Ok of 'a | `Error of string] ;;
Error: The type constructor string expects 2 argument(s),
but is here applied to 0 argument(s)
Есть ли способ сделать конструктор типов, который может эффективно "заменять различные типы" на int в [> `Ok of int | `Error of string]
?