Haskell中的产品类型易于定义:
data Person String String
是两种类型的乘积。两种类型的余积是
type Shape=Either Circle Rectangle
但是,尽管该产品很容易扩展到三种或更多种类型,但对于余积来说似乎并不那么简单。这种差异背后是否有理论基础,还是纯粹的技术原因?
Haskell中的产品类型易于定义:
data Person String String
是两种类型的乘积。两种类型的余积是
type Shape=Either Circle Rectangle
但是,尽管该产品很容易扩展到三种或更多种类型,但对于余积来说似乎并不那么简单。这种差异背后是否有理论基础,还是纯粹的技术原因?
data Apple = Gala | Fuji | PinkLady
data Orange = Navel | Blood
data Berry = Blueberry | Cranberry | Raspberry
data Fruit = Apple Apple
| Orange Orange
| Berry Berry
在这里,Fruit
是Apple
、Orange
和Berry
的余积1。
请注意,非标记联合体不是余积。
1: 嗯,有点。 Fruit
还包含一个额外的元素 ⊥
。 请参见下文。
data Shape = Either Circle Rectangle
您可能的意思是:
type Shape = Either Circle Rectangle
data
,则已定义了一个名为Either
的单构造产品类型。这是完全合法的。如果您使用type
,则将Shape
定义为另一个名称,其等同于Either Circle Rectangle
,这是Circle
和Rectangle
的余积。
(,)
类型构造函数与Set中的笛卡尔积进行比较。如果我们想要Int
和Int
的乘积,则会得到:
⊥ ∈ (Int, Int)
(在Hask中),但是⊥ ∉ Int ⨯ Int
(在Set中)。(,)
与笛卡尔积不同,因为它包含一个额外的成员⊥
。我们可以重复异构并集的论证:
⊥ ∈ Either Int Int
(在Hask中),但是⊥ ∉ Int ⊔ Int
(在Set中)。⊥
,而Set中的等效结构则没有。
对于 Hask 中的每种类型 T
,我们可以构造一个函数 T -> T
,使得对于所有的 x
,都有 f x = ⊥
。因此,如果 Hask 中的对象是指向集合(pointed sets),那么 ⊥
必须是基点。请注意,所有这样的 f
都是严格函数。
然而,让 g
成为任何惰性(正确的术语实际上是“非严格”)函数。根据严格性的定义,g ⊥ ≠ ⊥
。但是,根据第一条,这与 Hask 是指向集合范畴的前提相矛盾。
另外,积和余积结构不同,类似于 Set 的结构不同。对于积:
(⊥, ⊥) ∈ (Int, Int)
(在 Hask 中),但是(⊥, ⊥) ∉ Int ⊗ Int
(在 Pointed Set 中)。(,)
。余积也有同样的问题:
Left ⊥ ∈ Either Int Int
(在Hask中),但Left ⊥ ∉ Int ⊕ Int
(在指向集合中)。因此,集合和指向集合都不完全等同于范畴Hask。正如Haskell Wiki上Hask页面所述,在Haskell中,“乘积”和“余积”类型根本不符合范畴乘积和余积的定义。因此,严格来说,在Haskell中不存在乘积和余积。
这是坏消息。好消息是还有救。
考虑 Hask 中的所有严格函数和严格构造函数。结果是 Hask 的子范畴,也是 Pointed Set 的子范畴。这个子范畴是笛卡尔闭范畴。Apple
是一种类型,Orange
是一种类型,而Fruit
是两者的余积。 - Dietrich Epp⊥
,那么这意味着Hask中的所有态射(函数)都是严格的(这是“严格”的定义)。这是不正确的,因此Hask不是指向集合的范畴。 - Dietrich Eppg ⊥ = ⊥
的函数 g
(参见Wikipedia)。而惰性函数则是非严格函数,因此 g ⊥ ≠ ⊥
。除非你有一个与“非严格”不同的“惰性”的定义。 - Dietrich Epp
data Foo = Bar Int | Baz String
。 - OwenInt
和String
是类型,而Foo
是Int
和String
的余积。 - Dietrich Epp⊥
,标记联合就是余积。 - Dietrich Epp