为什么OCaml的记录类型声明不是同义词?

问题描述 投票:0回答:1

https://cs3110.github.io/textbook/chapters/data/type_synonym.html

正如我们在上面看到的,

type a = int * int * int

type a
int * int * int
的同义词。

所以,如果我们用多个名称声明

int * int * int
,它们都是相同的类型。

type a = int * int * int
type b = int * int * int
type c = int * int * int

a
b
c
是相同的类型。

他们没有数据构造函数。事实上,不需要,也不应该,因为它们只是一个同义词。

但是,当我们看记录时,情况就大不一样了。

type a = { name : string }
type b = { name : string }
type c = { name : string }

a
b
c
是不同的类型。 我们可以通过下面的代码来证明它。

({ name = "something" } : a) = ({ name = "something" } : b) ;;

// This expression has type b but an expression was expected of type a

它就像 Haskell 中的“newtype”,没有使用数据构造函数。

听说在OCaml中,记录是一个原始的概念,它们有自己的身份。 (你可以从下面的网址看到它。)

记录类型没有类型构造函数?

如果那样,为什么元组和记录的行为不同??

这让我很困惑。

了解到记录格式重复的问题可以通过使用模块来解决。 所以这种混乱没什么大不了的。

但是我想知道为什么元组和记录之间存在不一致

constructor ocaml record type-synonyms
1个回答
4
投票

主要是类型推断。当你写一个函数

let f x = x.a

然后类型系统将无法判断

f
的类型,如果它可以是任何带有字段
a
的记录类型。

有解决歧义的方法,即行多态性,这是 OCaml 用于推断对象类型的方法:

let f o = o#a  (* infers type f : < a : 'a; .. > -> 'a *)

在这里,

<a : t; ..>
表示具有
a
类型
t
的任何对象类型。然而,缺点是这种灵活性需要更重量级和昂贵的对象运行时表示。

也就是说,OCaml 的姊妹语言 Standard ML 确实使记录和元组成为同一件事(字面意思是,

a * b * c
只是 SML 中
{1 : a, 2 : b, 3 : c}
的简写),但随后需要程序员将类型注释插入到解决可能的歧义,如上例所示。

© www.soinside.com 2019 - 2024. All rights reserved.