2012-05-09 30 views

回答

3

我可以看到代数数据类型和面向对象类风格类之间的三个主要区别,不包括(im)可变性因为它有所不同。

  • 代数数据类型允许总和以及产品,而OO风格的类只允许产品。
  • OO风格的类允许您将复杂的数据项与其接受的操作捆绑在一起,而代数数据类型则不然。
  • 代数数据类型不区分传递给构造函数的数据和存储在结果值中的数据,而OO风格的类可以(或可以))。

我故意忽略的一件事是子类型。尽管绝大多数面向对象语言允许您继承(非最终的,非密封的,当前可访问的)类,并且绝大多数通用ML家族函数式语言不支持,但显然可以完全禁止假设继承OO(或至少类OO)语言,同样可以在代数数据类型中生成子类型和超类型;后者的有限的示例,请参阅this page on O'Haskell,已成功通过Timber

+1

所以ADT不需要*关闭*? Haskell的抽象数据类型不允许子类型(通过http://blog.tmorris.net/algebraic-data-types-again/) – canadadry

+0

@BonAmi不,抽象数据类型并不需要关闭。正如你所指出的,Haskell的是,但斯卡拉当然不一定(如果你可以称为案例类ADTs)。 –

3

类是不仅仅是一个类型定义更多 - 在大多数面向对象语言类实际上是提供各种松散的相关功能厨房水槽的功能。

特别是,类作为一种模块,为您提供数据抽象和命名空间。代数数据类型没有内置,模块化通常作为独立的正交特征(通常是模块)提供。

3

在某种意义上,人们可以这样看待它。每种语言都有很多机制来创建用户定义的类型。在功能性(ML,Haskell风格)语言中,唯一一个是创建ADT。 (Haskell的新类型可以被看作ADT的退化情况)。在OO语言中,它是类。在程序语言中,它是structrecord

毫无疑问,用户定义的数据类型的语义因语言而异,在范式#1中的语言和范式#2中的语言都不尽相同。 @ Pharien's Flame已经概述了典型的差异。

8

Algebraic data types如此命名是因为它们形成“初始代数”,

+ represents sum types (disjoint unions, e.g. Either). 
• represents product types (e.g. structs or tuples) 
X for the singleton type (e.g. data X a = X a) 
1 for the unit type() 
and μ for the least fixed point (e.g. recursive types), usually implicit. 

从这些运营商的所有常规数据类型可以构造。 代数数据类型也支持参数化多义性 - 意味着它们可以用作任何基础类型的常量,并具有静态安全性保证。此外,ADT提供统一的语法来引入和消除数据类型(通过构造函数和模式匹配)。例如。

-- this defines a tree 
data Tree a = Empty | Node a (Tree a) (Tree a) 

-- this constructs a tree 
let x = Node 1 (Node 2 Empty) Empty 

-- this deconstructs a tree 
f (Node a l r) = a + (f l) + (f r) 

代数数据类型的丰富性和均匀性,与它们是不可变的事实一起,从OO对象区别开来,这在很大程度上:

  • 仅代表产品类型(所以没有递归或总和-types)
  • 不支持的模式匹配
  • 是可变
  • 不支持参数多态性
+0

嗯。不是继承类加法类型的子类? (所以一个类基本上是一个开放的总和?)我也看不出参数多态如何与代数数据类型相关联。当然,你可以通过其他类型对它们进行参数化,但是你能不能用类来做呢?类型递归通常也适用,对吧? –

+0

是的,有足够的扩展,你可以到那里:“仿制药,子类的组合,和虚拟调度支持denition和对象 - 面向对象编程语言的有限使用广义代数的数据类型” - http://research.microsoft。 COM/EN-US/UM /人/ akenn /仿制药/ gadtoop.pdf –