gpt4 book ai didi

ocaml - 结合参数多态性和多态变体(反引号类型)

转载 作者:行者123 更新时间:2023-12-04 18:18:06 26 4
gpt4 key购买 nike

假设我有一个由多个多态变体(协变)组成的类型,例如:

[> `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

试图猜测编译器将用于未绑定(bind)类型变量的名称并将其作为参数添加到左侧也不起作用,并且会产生非常奇怪的错误消息。
$ 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)

有没有一种方法可以在 [> `Ok of int | `Error of string] 中创建一个可以有效地“替换不同类型”的 int 类型构造函数? ?

最佳答案

这不是方差或参数多态性的问题,而是行多态性的问题。当您添加 ><它还添加了一个隐式类型变量,即行变量,它将保存“完整”类型。您可以在错误中看到此类型变量:

[> `Error of string | `Ok of 'a ] as 'b

注意 as 'b最后的部分。

为了给类型起别名,您必须使类型变量显式,因此您可以将其作为别名上的类型参数引用:
type ('a, 'r) error = [> `Ok of 'a | `Error of string ] as 'r

另请注意,如果您有或何时会遇到对象,这也适用于那里。具有 .. 的对象类型有一个隐式类型变量,您需要将其显式化才能为其命名:
type 'r obj = < foo: int; .. > as 'r

关于ocaml - 结合参数多态性和多态变体(反引号类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59832334/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com