我正在努力完全理解Haskell的所有概念.
代数数据类型在哪些方面类似于泛型类型,例如在C#和Java中?它们有何不同?无论如何,他们有什么代数呢?
我熟悉通用代数及其环和字段,但我对Haskell的类型如何工作只有一个模糊的概念.
Haskell的代数数据类型被命名为,因为它们对应于类别理论中的初始代数,给出了一些定律,一些操作和一些操作符号.我们甚至可以使用代数表示法来描述常规数据结构,其中:
+
表示总和类型(例如,不相交的联合Either
).
•
代表产品类型(例如结构或元组)
X
对于单身人士类型(例如data X a = X a
)
1
对于单位类型 ()
并且?
对于最不固定的点(例如递归类型),通常是隐含的.
用一些额外的表示法:
X²
对于 X•X
事实上,你可能会说(以下布伦特Yorgey)是一个Haskell数据类型是有规律的,如果它可以在来表示1
,X
,+
,•
,和至少一个动点.
使用这种表示法,我们可以简明地描述许多常规数据结构:
单位: data () = ()
1
选项: data Maybe a = Nothing | Just a
1 + X
列表: data [a] = [] | a : [a]
L = 1+X•L
二叉树: data BTree a = Empty | Node a (BTree a) (BTree a)
B = 1 + X•B²
其他业务持有(取自Brent Yorgey的论文,参考文献中列出):
扩展:展开修复点有助于思考列表.L = 1 + X + X² + X³ + ...
(也就是说,列表是空的,或者它们有一个元素,或者两个元素,或者三个,或者......)
组合物,?
给定类型F
和G
组合物F ? G
是构建"由G-结构制成的F-结构"的类型(例如R = X • (L ? R)
,在哪里L
是列表,是玫瑰树).
区分,数据类型D的导数(给定为D')是具有单个"洞"的D结构的类型,即,不包含任何数据的区别位置.令人惊讶地满足与微积分差异相同的规则:
1? = 0
X? = 1
(F + G)? = F' + G?
(F • G)? = F • G? + F? • G
(F ? G)? = (F? ? G) • G?
参考文献:
种类和函数和类型,哦我的!,Brent A. Yorgey,Haskell'10,2010年9月30日,美国马里兰州巴尔的摩
我左边的小丑,右边的笑话(Dissecting Data Structures),Conor McBride POPL 2008
Haskell中的"代数数据类型"支持完整的参数多态,这是泛型的技术上更正确的名称,作为列表数据类型的一个简单示例:
data List a = Cons a (List a) | Nil
是等价的(尽可能多,并忽略非严格的评价等)
class List { class Cons : List { a head; List tail; } class Nil : List {} }
当然,Haskell的类型系统允许更多...有趣地使用类型参数,但这只是一个简单的例子.关于"代数类型"的名称,我真的从来没有完全确定它们被命名的确切原因,但是假设它是由于类型系统的数学基础.我认为原因归结为ADT的理论定义是"一组构造者的产物",但是自从我逃离大学以来已经过了几年,所以我再也记不起具体细节了.
[编辑:感谢Chris Conway指出我的愚蠢错误,ADT当然是总和类型,提供产品/字段元组的构造函数]
在通用代数中 ,代数由一些元素集(将每个集合视为一个类型的值集)和一些将元素映射到元素的操作组成.
例如,假设您有一种"列表元素"和一种"列表"类型.作为操作,你有"空列表",这是一个返回"列表"的0参数函数,以及一个带有两个参数的"cons"函数,一个"列表元素"和一个"列表",并产生一个"列表" ".
在这一点上,有许多符合描述的代数,因为可能会发生两件不希望的事情:
"list"集中可能存在无法从"空列表"和"cons操作"构建的元素,即所谓的"垃圾".这可以是从天空中掉落的某个元素开始的列表,也可以是没有开头的循环或无限列表.
应用于不同参数的"cons"的结果可以是相等的,例如,将非空列表中的元素提供可以等于空列表.这有时被称为"混乱".
具有这些不期望的属性的代数被称为 initial,这是抽象数据类型的预期含义.
名称initial起源于从初始代数到任何给定代数只有一个同态的属性.基本上,您可以通过应用其他代数中的运算来评估列表的值,并且结果是明确定义的.
多态类型变得更加复杂......
他们被称为代数的一个简单原因; 有sum(逻辑析取)和product(逻辑合取)类型.和类型是一个有区别的联合,例如:
data Bool = False | True
产品类型是具有多个参数的类型:
data Pair a b = Pair a b
在O'Caml中,"产品"更明确:
type 'a 'b pair = Pair of 'a * 'b
Haskell的数据类型称为"代数",因为它们与分类初始代数有关.但那种方式就是疯狂.
@olliej:ADT实际上是"和"类型.元组是产品.