假设我有一个由多个多态变体(协变)组成的类型,例如:
[> `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 ]
似乎可以正常工作。
$ ocaml
OCaml version 4.07.0
# type 'a error = [ `Ok of 'a | `Error of string ] ;;
type 'a error = [ `Error of string | `Ok of 'a ]
#
但是,将类型参数显式标记为协变并不能挽救原始示例。
$ 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 in [> `Ok of int | `Error of string]
?