为什么Haskell中的coproduct类型没有简单的语法?

Moz*_*lah 8 computer-science haskell functional-programming category-theory

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

data Person String String 
Run Code Online (Sandbox Code Playgroud)

是两种类型的产品.两种类型的副产品是

type Shape=Either Circle Rectangle
Run Code Online (Sandbox Code Playgroud)

但是,虽然产品可以轻松扩展到三种或更多类型,但对副产品来说似乎并不那么简单.这种差异背后有理论上的理由,还是纯粹技术性的原因?

Die*_*Epp 23

data Apple = Gala | Fuji | PinkLady
data Orange = Navel | Blood
data Berry = Blueberry | Cranberry | Raspberry

data Fruit = Apple Apple
           | Orange Orange
           | Berry Berry
Run Code Online (Sandbox Code Playgroud)

在这里,Fruit是一个副产品Apple,OrangeBerry1.

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

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

对已编辑问题的回复

data Shape = Either Circle Rectangle
Run Code Online (Sandbox Code Playgroud)

你可能意味着:

type Shape = Either Circle Rectangle
Run Code Online (Sandbox Code Playgroud)

如果使用data,则已使用名为的单个构造函数定义了产品类型Either.这是完全合法的.如果你使用type,你已经定义Shape为另一个名字Either Circle Rectangle,这是一个副产品CircleRectangle.

Hask与Set

让我们在Haskell,Hask中调用类型和函数的类别.这是它的通常名称.它确实符合类别的定义,假设你不仔细看我们称之为计算机的这些有限的东西.

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

  • ? ? (Int, Int) (在哈斯克),但是
  • ? ? Int ? Int (在Set中).

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

  • ? ? Either Int Int (在哈斯克),但是
  • ? ? Int ? Int (在Set中).

在每种情况下,Hask中的结构都包含一个附加元素?,即Set中的等效结构不具有.

Hask与Pointed集

Hask也不是尖集的类别.首先,Hask包含不是指向集态态的态射.

  1. 对于THask中的每一种类型,我们都可T -> T以为f x = ?所有人构造一个函数x.因此,?如果Hask中的对象是指向集,则必须是基点.请注意,所有这些f都是严格的功能.

  2. 但是,让g任何懒惰(这里的正确术语实际上是"非严格")功能.通过严格的定义,g ? ? ?.然而,对于#1,这与Hask是尖集的类别的前提相矛盾.

另外,产品和副产品结构是不同的,其方式与结构与Set的结构不同的方式相似.对于产品,

  • (?, ?) ? (Int, Int) (在哈斯克),但是
  • (?, ?) ? Int ? Int (在尖头套装中).

这是从态射的问题得出的:在尖集中,所有函数都是严格的 - 这包括构造函数,如(,).副产品有同样的问题:

  • Left ? ? Either Int Int (在哈斯克),但是
  • Left ? ? Int ? Int (在尖头套装中).

结论

因此,Set和Pointed Set都不等于Hask类别.正如Haskell Wiki上的Hask页面所述,Haskell中的"product"和"coproduct"类型根本不符合分类产品和副产品的定义.严格来说,Haskell中不存在产品和副产品.

这是坏消息.有好消息.

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

  2. 考虑Hask中的所有总函数,如果它们为除了之外的每个输入产生相同的输出,则将两个函数视为相同的态射?.(这些输出必须不是?"total"的定义.)结果是Set的子类别.该子类别是笛卡尔闭合类别.

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

最后一点好消息.假设程序的严格版本终止,可以将严格的函数修改为惰性函数而不改变整个程序的输出.因此,您可以假装?不存在并使用类别理论完成一些工作,但仍然编写利用延迟评估的程序.

懒惰的总结

假装Hask有产品和副产品不会让你遇到麻烦.

  • @MoziburUllah:Hask不是尖集的类别.尖集的态射必须将基点映射到基点.如果基点是"⊥",那么这意味着Hask中的所有态射(函数)都是严格的(这是"严格"的定义).事实并非如此,因此Hask不是尖集的类别. (2认同)