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,Orange和Berry1.
请注意,未标记的联合不是副产品.
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,这是一个副产品Circle和Rectangle.
让我们在Haskell,Hask中调用类型和函数的类别.这是它的通常名称.它确实符合类别的定义,假设你不仔细看我们称之为计算机的这些有限的东西.
让我们将Hask与Set类别进行比较.这很自然,因为Hask是一个具体的类别.将(,)Hask中的类型构造函数与Set中的笛卡尔积进行比较.如果我们想要的产品Int和Int,我们得到:
? ? (Int, Int) (在哈斯克),但是? ? Int ? Int (在Set中).所以你可以看到类型构造函数(,)与笛卡尔积不同,因为它包含一个额外的成员,?.我们可以重复不相交联盟的论点:
? ? Either Int Int (在哈斯克),但是? ? Int ? Int (在Set中).在每种情况下,Hask中的结构都包含一个附加元素?,即Set中的等效结构不具有.
Hask也不是尖集的类别.首先,Hask包含不是指向集态态的态射.
对于THask中的每一种类型,我们都可T -> T以为f x = ?所有人构造一个函数x.因此,?如果Hask中的对象是指向集,则必须是基点.请注意,所有这些f都是严格的功能.
但是,让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中不存在产品和副产品.
这是坏消息.有好消息.
考虑Hask中的所有严格函数和严格构造函数.结果是Hask的子类别,它也是Pointed Set的子类别.该子类别是笛卡尔闭合类别.
考虑Hask中的所有总函数,如果它们为除了之外的每个输入产生相同的输出,则将两个函数视为相同的态射?.(这些输出必须不是?"total"的定义.)结果是Set的子类别.该子类别是笛卡尔闭合类别.
因此,只要您按照正确的规则进行游戏,您仍然可以使用笛卡尔闭合类别.您甚至可以从两个不同的类别中进行选择!但是,如果您遵循这些规则,那么您正在使用Haskell的子集.
最后一点好消息.假设程序的严格版本终止,可以将严格的函数修改为惰性函数而不改变整个程序的输出.因此,您可以假装?不存在并使用类别理论完成一些工作,但仍然编写利用延迟评估的程序.
假装Hask有产品和副产品不会让你遇到麻烦.