types - 在 OCaml 中,一个用冒号声明其标签的变体

标签 types ocaml variant

查看以下代码:

type z = Z of z

type 'a s = Z | S of 'a

type _ t = Z : z t | S : 'n t -> 'n s t
最后一行包含一个通用变体,或者看起来像一个变体,但没有使用关键字 of它使用冒号符号 : .这是为什么?我应该如何阅读这种类型?
查看类型声明的 OCaml 语法:https://ocaml.org/manual/types.html这是否真的是一个变体似乎并不明显,甚至看起来这是一个标签和一个变体的混合体。

最佳答案

这是 generalized algebraic data type 的定义(GADT)。此语言功能是在 OCaml 的 4.0 版本中引入的,并且常规代数数据类型 (ADT) 的语法使用此列变体进行了扩展,以启用特定于构造函数的约束。
常规 ADT 语法 <Constr> [of <args>]用于引入构造函数<Constr>具有指定参数的,例如,

type student = Student of string * int
通用语法,<Constr> : [<args>] -> <constr>用途 :而不是 of但是添加了一个额外的地方来指定类型约束,例如,
type student = Student : string * int -> student
约束必须是定义类型的实例。当定义的类型或构造函数参数(或两者)是多态的,即引用类型变量时,它很有用。一个更好的例子是表达式语言的类型安全抽象语法树,例如,
type _ exp = 
  | Int : int -> int exp
  | Str : string -> string exp
  | Cat : string exp * string exp -> string exp
  | Add : int exp * int exp -> int exp
使用这种表示,我们可以编写一个静态类型的解释器,这样我们就不必处​​理案例 Add (Str "foo", Int 42)由于 Cat 的限制,不可能构造这样的值构造函数,它要求两个参数都具有 string类型。
GADT 的另一个用例是启用可用于实现动态类型和临时多态性的存在类型,如 Haskell 类型类。在存在构造函数中,在构造函数参数类型中出现的一些类型变量不存在于约束类型中,例如,
type show = Show : {data : 'a; show : 'a -> string} -> show
let show (Show {data=x;show}) = show x
所以现在我们可以有一个异构的容器,
let entries = [
    Show {data=42; show=string_of_int};
    Show {data="foo"; show=fun x -> x};
]
我们可以展示,
# List.map show entries;;
- : string list = ["42"; "foo"]

关于types - 在 OCaml 中,一个用冒号声明其标签的变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69683695/

相关文章:

c++ - 使用结构的隐式类型转换

ocaml - MetaOCaml 非限定构造函数

types - 将多个变体合并为一个变体

c++ - 创建 VARIANT 的 CMap 的正确方法

c - 这个双重类型定义会导致访问冲突吗?

sql - 在oracle中检索并插入类型对象

types - 使用相同的 Rust channel (mpsc) 发送不同的类型

ocaml - 在 Queue 数据结构中使用惰性求值有什么好处?

haskell - 保存我正在运行的顶层以供以后使用

java - JAXB:无法解码 JAXBElement<?>,取而代之的是获取 ElementNSImpl