这两个概念都允许创建新的数据类型。 我能看到的唯一区别是,在函数式语言中,可以对代数数据类型执行模式匹配。但OO语言没有类似的简洁功能。这是一个准确的陈述吗?
答案 0 :(得分:6)
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.
从这些运算符可以构造所有常规数据类型。 代数数据类型也支持参数多态性 - 这意味着它们可以用作任何基础类型的constainer,具有静态的安全保证。此外,为ADT提供了统一的语法,用于引入和消除数据类型(通过构造函数和模式匹配)。 E.g。
-- 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对象区分开来,这主要是:
答案 1 :(得分:4)
我可以看到代数数据类型和OO风格类之间的三个主要区别,不计算(im)可变性,因为它有所不同。
我故意遗漏的一件事是分组。虽然绝大多数OO语言允许你子类化(非最终的,非密封的,当前可访问的)类,而绝大多数通常是ML系列的函数式语言都没有,但显然可以在假设中完全禁止继承。 OO(或至少类似OO)语言,同样可以在代数数据类型中产生子类型和超类型;对于后者的有限示例,请参阅this page on O'Haskell已成功的Timber
答案 2 :(得分:2)
一个类不仅仅是一个类型定义 - 大多数OO语言中的类都是厨房接收器功能,它们提供各种松散相关的功能。
特别是,类充当一种模块,为您提供数据抽象和命名空间。代数数据类型没有内置,模块化通常作为单独的正交特征(通常是模块)提供。
答案 3 :(得分:2)
在某种意义上,人们可以这样看待它。每种语言都只有很多机制来创建用户定义的类型。在功能(ML,Haskell风格)语言中,唯一的一种是创建ADT。 (Haskell的新类型可以看作是ADT的退化案例)。在OO语言中,它是类。在过程语言中,它是struct
或record
。
不言而喻,用户定义的数据类型的语义因语言而异,从范式#1中的语言到范例#2中的语言更是如此。 @ Pharien's Flame已经概述了典型的差异。
答案 4 :(得分:0)
代数数据类型的概念是否类似于OO语言中的类定义?
在功能语言中,可以对代数数据类型执行模式匹配。但是面向对象语言没有可比的简洁功能。这是正确的说法吗?
那是它的一部分。
正如Andreas所说,类是从Simula派生的静态类型的面向对象的语言(如C ++,Java和C#)中的一个厨房接收器功能。在这方面,班级是千篇一律,但无人掌握:它们严重地解决了许多问题。
在C ++,Java和C#中比较香草ML和Haskell与OO,您会发现:
因此,ADT并不是真正地“类似于”类,因为它们仅解决了一个特定的问题:一层深的类层次结构。从这个意义上讲,我们可以看到两个近似的观察结果:
您还可以查看GoF设计模式。它们已使用C ++中的类表示。功能等效项并不总是ADT,而是lambda函数(而不是命令模式)和高阶函数(例如map
和fold
(而不是访问者模式)之类的东西。