[英]Why do we need “Algebraic Data Types”?
我已经阅读了代数数据类型的一些解释:
这些文章提供了非常详细的描述和代码示例。
起初我认为代数数据类型只是用于轻松定义某些类型,我们可以将它们与模式匹配相匹配。 但在阅读完这些文章之后,我发现那里甚至没有提到“模式匹配”,内容看起来很有趣,但比我预期的要复杂得多。
所以我有一些问题(这些文章没有回答):
我们应该从Haskell wiki文章Algebraic Data Types开始
在这里,不久,只是我的愿景:
type Boolean = True | False
type Boolean = True | False
表示Boolean是True
和False
并集(coproduct)。 Cat(height: Height, weight: Weight)
是Height
和Weight
的“元组”(更一般地说 - 产品)。 产品(更多)表示来自OOP,“联合产品”的“部分”关系 - “是”(但以相反的方式)。 它还为我们提供了一种以多方式方式在运行时调度行为的方法(就像它在CLOS中一样 ):
sealed trait Animal
case class Cat extends Animal
case class Dog extends Animal
def move(c: Animal) = c match {
case Cat(...) => ...
case Dog(...) =>
case a: Animal => ...//if you need default implementation
}
哈斯克尔样:
data Animal = Dog | Cat //coproduct
let move Dog d = ...
let move Cat c = ...
代替:
trait Animal {
...
def move = ...
}
class Cat(val ...) extends Animal {
override def move = ...
}
class Dog(val ...) extends Animal {
override def move = ...
}
PS理论上,如果你用代数方式对世界进行建模,并且你的功能是完全和纯粹的 - 你可以证明你的应用是正确的。 如果它编译 - 它工作:)。
PS2。 我还应该提一下,Scala的类型层次结构中包含Any
,对于类型安全来说并不是那么好(但是对于Java和IO的互操作很好),因为它打破了GADT定义的漂亮结构。 不仅如此, case class
可能同时是GADT(代数)和ADT(抽象),这也减少了保证。
你提到的博客文章更多的是关于代数数据类型的数学方面,关于它们在编程中的实际应用。 我认为大多数函数式程序员首先通过在某些编程语言中使用它们来学习代数数据类型,然后才研究它们的代数属性。
事实上,博客文章的意图从一开始就是明确的:
在这一系列的帖子中,我将解释为什么Haskell的数据类型被称为代数 - 不提类别理论或高级数学。
无论如何,代数类型的实际用途最好通过玩它们来欣赏。
例如,假设您要编写一个函数来交叉平面上的两个段。
def intersect(s1: Segment, s2: Segment): ???
结果应该是什么? 写作很诱人
def intersect(s1: Segment, s2: Segment): Point
但如果没有交集怎么办? 有人可能会尝试通过返回null
或抛出NoIntersection
异常来修补该角落情况。 但是,当它们位于同一直线上时,两个段也可能在多个点上重叠。 在这种情况下我们该怎么做? 抛出另一个例外?
代数类型方法是设计一种涵盖所有情况的类型:
sealed trait Intersection
case object NoIntersection extends Intersection
case class SinglePoint(p: Point) extends Intersection
case class SegmentPortion(s: Segment) extends Intersection
def intersect(s1: Segment, s2: Segment): Intersection
有许多实际情况,这种方法感觉很自然。 在缺少代数类型的其他一些语言,人们必须采取例外,以null
秒(见数十亿美元的错误 ),非密封类(使它不可能让编译器检查模式匹配的全面性),或到该语言提供的其他功能。 可以说,OOP中的“最佳”选项是使用访问者模式来编码没有这些特征的语言中的代数类型和模式匹配。 尽管如此,在scala中直接支持语言更方便。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.