【问题标题】:Why isn't there a simple syntax for coproduct types in Haskell?为什么 Haskell 中没有用于联积类型的简单语法?
【发布时间】:2012-12-24 08:52:58
【问题描述】:

Haskell 中的产品类型很容易定义:

data Person String String 

是两种类型的产物。两种类型的联积是

type Shape=Either Circle Rectangle

但是,虽然产品很容易扩展到三种或更多类型,但对于副产品来说似乎并不那么简单。这种差异背后是否有理论依据,还是纯粹是技术原因?

【问题讨论】:

  • 也许我想错了定义,但我认为副产品类型也很简单:data Foo = Bar Int | Baz String
  • 这就是我最初的想法。但是 Bar & Baz 不是类型,它们是值构造函数。如果它们是类型,它们将被数据声明为类型。
  • @MoziburUllah:这不是重点。 IntString 是类型,FooIntString 的联积。
  • 或许不是,我得再考虑一下。
  • @DietrichEpp:是的,这就是我最初的想法。但是HaskellWiki 上的页面指出,Haskell 类型系统没有形成类别(但通过简单的修改它可以),也没有“有总和、乘积或初始对象,并且 () 不是一个终端对象”。它们也没有对副产品使用明显的语法。这是我试图理解的,但可能在问题中没有说得足够清楚。

标签: haskell functional-programming computer-science category-theory


【解决方案1】:
data Apple = Gala | Fuji | PinkLady
data Orange = Navel | Blood
data Berry = Blueberry | Cranberry | Raspberry

data Fruit = Apple Apple
           | Orange Orange
           | Berry Berry

这里,FruitAppleOrangeBerry 的副产品1

请注意,未标记的联合不是副产品。

1:嗯,有点。 Fruit 还包含一个额外的元素 。见下文。

对已编辑问题的回复

data Shape = Either Circle Rectangle

你的意思可能是:

type Shape = Either Circle Rectangle

如果您使用data,则您定义了一个产品类型,其中包含一个名为Either 的构造函数。这是完全合法的。如果您使用type,您将Shape 定义为Either Circle Rectangle 的另一个名称,它是CircleRectangle 的联产品。

Hask 与 Set

我们把Haskell中的类型和函数的范畴叫做Hask。这是它的常用名称。它确实符合类别的定义,假设您没有仔细研究这些我们称为计算机的有限事物。

让我们将 Hask 与类别 Set 进行比较。这是很自然的,因为 Hask 是一个具体的类别。比较 Hask 中的 (,) 类型构造函数和 Set 中的笛卡尔积。如果我们想要IntInt 的乘积,我们得到:

  • ⊥ ∈ (Int, Int)(在 Hask 中),但是
  • ⊥ ∉ Int ⨯ Int(在集合中)。

所以你可以看到类型构造函数(,)与笛卡尔积不一样,因为它包含一个额外的成员。我们可以重复不相交并集的论点:

  • ⊥ ∈ Either Int Int(在 Hask 中),但是
  • ⊥ ∉ Int ⊔ Int(在集合中)。

在每种情况下,Hask 中的结构都包含一个附加元素 ,而 Set 中的等效结构则没有。

Hask 与 Pointed 集

Hask 也不是指向集合的范畴。首先,Hask 包含非指向集态射的态射。

  1. 对于 Hask 中的每个类型T,我们可以构造一个函数T -> T,使得f x = ⊥ 对应所有x。因此, 必须是基点,如果 Hask 中的对象是指向集的话。请注意,所有此类f 都是严格函数。

  2. 但是,让g 成为任何惰性(这里的正确术语实际上是“非严格”)函数。根据严格的定义,g ⊥ ≠ ⊥。但是,对于 #1,这与 Hask 是指向集的范畴的前提相矛盾。

此外,产品和副产品的结构是不同的,类似于结构与 Set 的结构不同的方式。对于产品,

  • (⊥, ⊥) ∈ (Int, Int)(在 Hask 中),但是
  • (⊥, ⊥) ∉ Int ⊗ Int(在尖集中)。

这源于态射的问题:在指向集合中,所有函数都是严格的——这包括构造函数,例如(,)。副产品也有同样的问题:

  • Left ⊥ ∈ Either Int Int(在 Hask 中),但是
  • Left ⊥ ∉ Int ⊕ Int(在尖集中)。

结论

所以,Set 和 Pointed Set 都不完全等同于 Hask 范畴。正如 Haskell Wiki 上的 Hask 页面中所述,Haskell 中的“产品”和“副产品”类型根本不符合分类产品和副产品的定义。所以严格来说,Haskell 中不存在产品和副产品。

这是个坏消息。好消息。

  1. 考虑 Hask 中的所有严格函数和严格构造函数。结果是 Hask 的一个子类别,它也是 Pointed Set 的一个子类别。该子类别是一个笛卡尔封闭类别。

  2. 考虑 Hask 中的所有总函数,如果两个函数对除 之外的每个输入产生相同的输出,则将它们视为相同的态射。 (根据“total”的定义,这些输出不一定是。)结果是Set 的子类别。该子类别是一个笛卡尔封闭类别。

因此,只要您遵循正确的规则集,您仍然可以使用笛卡尔封闭类别。您甚至可以从两个不同的类别中进行选择!但是,如果您遵守这些规则,那么您正在使用 Haskell 的一个子集。

还有最后一点好消息。假设程序的严格版本终止,严格函数可以修改为惰性函数而不改变整个程序的输出。因此,您可以假装 不存在并使用范畴论完成一些工作,但仍然编写利用惰性求值的程序。

懒人总结

假装 Hask 有产品和副产品不会给你带来麻烦。

【讨论】:

  • Gala、Fuji 等不是类型,而是价值。
  • @MoziburUllah:我从来没有说过他们是类型。 Apple 是一个类型,Orange 是一个类型,Fruit 是两者的联乘。
  • @MoziburUllah:如果你想获得技术,你会说GalaFuji等是空构造函数。
  • @MoziburUllah:Hask 不是尖集的范畴。点集的态射必须将基点映射到基点。如果基点是,那么这意味着Hask 中的所有态射(函数)都是严格的(这是“严格”的定义)。这不是真的,因此 Hask 不是指向集合的范畴。
  • @DietrichEpp 抱歉,我认为您误会了我。我理解你的推理和定义,很好。我只是建议您编辑您的答案 - 论点 (2) - 正如您目前所说的“根据严格的定义,g ⊥ ≠ ⊥。”,这是严格的 否定。这掩盖了你的论点。也许您的意思是“根据非严格性(懒惰)的定义”?尽管应该注意一些惰性函数,其中 g ⊥ = ⊥(例如 g x = ⊥)。对于您的论点,您只需要存在一个惰性函数 g 其中 g ⊥ ≠ ⊥。
猜你喜欢
  • 1970-01-01
  • 2016-04-16
  • 2014-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多