【问题标题】:Structural typing for sum types总和类型的结构类型
【发布时间】:2020-05-16 06:23:11
【问题描述】:

对于产品类型,名义类型与结构类型是一种设计决策,在每种情况下都有直接的解释;您可以定义两个相同的记录类型,以相同的顺序具有相同的字段,但名称不同;它们是兼​​容的还是不兼容的;很容易看出每种可能性如何导致一个连贯的类型系统。

我不清楚这同样适用于 sum 类型;这些的全部意义在于您保留标签名称,以便您可以创建值并稍后区分它们。但在讨论名义类型与结构类型的讨论中,我找不到任何提及这个问题的地方。

是这样吗:

  1. 当然名义型和结构型只适用于产品类型,总和类型必须是名义型的,这一点不言而喻,所以没人费心提及。
  2. 实际上,sum 类型可以是结构化的,采用以下我没有想到的方式...
  3. 还有别的吗?

【问题讨论】:

  • Typescript 追求的是结构化类型。当您忽略名称时,标签将变为part of that structure。我认为这种方法相当不合理,但他们就是这样做的。
  • @bob 嗯!我不知道打字稿,但是如果我正确理解了该代码片段,它似乎将名称变成了字符串字段?从而实现名义类型 - 名称作为一个区别因素保持存在 - 没有这样的名义类型系统?
  • 没错。他们称其为可区分联合(标记联合的同义词),其中特殊属性扮演判别式的角色,其值代表标签。如您所见,判别式的每个值都对应于类型构造函数的名称。这是相当令人困惑的部分,因为通常值构造函数的名称提供了标签,这些标签在编译期间不会被删除。
  • 因此,根据 Davislor 的回答,两个数据声明 Val/File 在 TS 中将被视为相等。这感觉不对,因为结构类型忽略了数据类型的语义部分,而这部分并未反映在其结构中。

标签: types functional-programming language-agnostic theory discriminated-union


【解决方案1】:

通过与您的讨论,我了解到您要问的是一种新语言是否可以将等价的 sum 类型视为相同。例如,如果语法类似于 ML,则可以定义

data Val  = Unparsed String | Parsed Int
data File = Filename String | FileDescriptor Int

对于 ValFile 是否被视为与产品类型相同的类型、可转换类型或不相关类型,您在此处具有完全相同的选择。让我们来看看一些选项。

请注意,运行时必须跟踪 sum 类型的哪个组件是活动的,但这不需要是类型名称或类型 ID(除非语言提供了直接查询活动类型的方法)。它可以静态地进行所有类型检查,将可能的格式枚举为任意整数,并将运行时与该值进行比较(例如,对匹配 0x02 的案例进行二进制搜索)。将其用作函数表或其他内容的索引。

结构类型

一种可能的简单实现是对它们进行鸭式输入。编写一种可以将File 传递给任何接受Val 的函数的函数式语言会很奇怪,它会正常工作。但它会起作用。该语言将查找定义,查看它们是否等效,并将它们视为彼此的别名。如果语言要求选项具有相同的名称,这可能不会让程序员感到惊讶。

标称类型

如果你尝试在 Haskell 中做同样的事情,它会告诉你这是两种不同的类型。要将一个转换为另一个,您需要编写一个解包和重新打包的函数,例如

fromVal (Unparsed path) = Filename path
fromVal (Parsed fd)     = FileDescriptor fd

糊状的中间

我上面写的转换函数显然不是最优的,因为这两种类型有完全相同的布局和实现。您无需做任何实际工作即可将其中一种转换为另一种。

语言在这里可能采取中间立场:您必须在类型之间显式转换,但转换是无操作的。更进一步的矛盾可能是需要在某处声明以启用这种微不足道的转换,有点像 C++ 中的 default 构造函数或 Haskell 中的 deriving。编译器将能够自动编写它。

这在命令式语言中很常见。例如,在 C 中,如果两种类型是“布局兼容”的,或者即使它们是前几个字段与布局兼容的产品类型,它们之间的类型双关语也能保证工作。

无处不在的套接字库依赖于它来实现struct sockaddr,它实际上是一个 sum 类型。但是,作为副作用,如果您实现了具有 32 位字段和 16 位字段的新网络协议,该语言会认为它与 IPv4 地址和 TCP 或 UDP 端口号兼容。由于类型兼容性是结构性的,因此没有办法禁用它(甚至无法让语言阻止你在脚下开枪,因为类型双关的方法是覆盖所有类型检查)。但是内核级编程经常需要这种类型的双关语。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多