代数数据类型的概念是否类似于OO语言中的类定义?

can*_*dry 6 functional-programming algebraic-data-types

这两个概念都允许创建新的数据类型.我能看到的唯一区别是,在函数式语言中,可以对代数数据类型执行模式匹配.但OO语言没有类似的简洁功能.这是一个准确的陈述吗?

Don*_*art 6

代数数据类型之所以如此命名是因为它们构成了"初始代数",

+ 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.
Run Code Online (Sandbox Code Playgroud)

从这些运算符中可以构造所有常规数据类型.代数数据类型也支持参数多态性 - 这意味着它们可以用作任何基础类型的constainer,具有静态的安全保证.此外,为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)
Run Code Online (Sandbox Code Playgroud)

代数数据类型的丰富性和一致性,以及它们是不可变的这一事实,将它们与OO对象区分开来,这在很大程度上:

  • 仅代表产品类型(因此没有递归或求和类型)
  • 不支持模式匹配
  • 是可变的
  • 不支持参数多态

  • 唔。子类化不是有点像添加类型加数吗?(所以一个类基本上是一个开放和?)我也没有看到参数多态性如何与代数数据类型联系起来。当然,您可以通过其他类型对它们进行参数化,但是您不能对类也这样做吗?类型递归通常也可以工作,对吗? (2认同)

Pth*_*ame 5

我可以看到代数数据类型和 OO 风格的类之间的三个主要区别,不计算(im)可变性,因为它们各不相同。

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

我故意从该列表中遗漏的一件事是子类型。虽然绝大多数面向对象语言允许您对类(非最终的、非密封的、当前可访问的)类进行子类化,而绝大多数一般的 ML 系列函数式语言则不允许,但显然可以在假设的情况下完全禁止继承OO(或至少类似OO)语言,同样可以在代数数据类型中产生子类型和超类型;有关后者的有限示例,请参阅O'Haskell 上的此页面该页面已被Timber接替