当我学习Scala/Haskell时,我看到了代数数据类型的概念。我已经阅读了维基百科上的解释,但我仍然有一个问题:为什么它在名称中使用“代数”这个词?它与“代数”有什么关系吗?
简单地说,我们必须考虑代数和类型之间的关系。Haskell的代数数据类型被命名为这样,因为它们对应于范畴论中的初始代数。
维基百科说:
在计算机编程中,特别是函数式编程和类型理论中,代数数据类型是一种复合类型,即通过组合其他类型而形成的类型。
让我们以Maybe a
数据类型为例:
data Maybe a = Nothing | Just a
Maybe a
表示它可能包含某个类型的内容,例如 Just Int
,但也可以为空 - Nothing
。在 Haskell 中,类型是对象,例如 Int
。运算符获取类型并生成新类型,例如 Maybe Int
。代数指的是代数数据类型由代数运算(sums
和 product
)创建的属性,其中:
例如,让我们来看看 Maybe a
的 sum
。首先,让我们定义一个 Add
类型:
data Add a b = Left a | Right b
|
表示or
,因此它可以是Left a
或Right b
。竖线|
告诉我们,我们上面定义的Maybe
是一个总和类型(sum type),这意味着我们可以使用Add
来编写它:type Maybe a = Add Nothing (Just a)
Nothing
这里是一个unit
类型:
在数学逻辑和计算机科学领域中,类型理论中的unit类型是一种只允许一个值的类型。
data Unit = Unit
或者在Haskell中使用()
。
Just a
是一种单例类型。单例类型是仅有一个值的类型。
data Just a = Just a
type Maybe a = Add () a
1
,和单例类型 - a
。现在我们可以说Maybe a
与1 + a相同。Bool
。当然,这种类型只能取两个可能的值:True 或 False。data EitherBool = Left Bool | Right Bool
左假,左真,右假,右真
。那么呢?data EitherBoolInt = Left Bool | Right Int8
EitherBoolInt
有2+2^8种可能的取值。很容易看出,对于任何构造函数和类型集合,这种结构都能给你一个数据类型,其可能的取值空间大小等于每个单独构造函数的可能值之和,因此被称为和类型。data BoolAndInt = BAndI Bool Int8
或者只是简单地
type BoolAndInt = (Bool, Int)