Haskell 学习笔记二:数据类型
Haskell 拥有非常神奇且优秀的数据类型系统。它非常先进,一些理念被其他的语言所借鉴,比如 Java 的 <T>
(generics)。
举个例子:
data Bool = True | False
这里就定义了 Bool
类型。Bool
可以是 True
或者 False
,他们都是 Bool
。
对 OOP 熟悉的同学肯定对 polymorphism
的概念了然于胸。Haskell 的类型系统会让你对 polymorphism 的理解更上层楼,它简直就是艺术品 ,写代码像写诗。
再举个例子,
data Coordinate = MkCoordinate Integer Integer
这里我们定义了 Coordinate
类型,数据是两个 Integer。MkCoordinate
被称为 constructor。新建一个实例的时候需要用到 constructor,后面跟具体的数据。比如新建一个 (0, 0) 的坐标(Coordinate)的话只需要这么做:
MkCoordinate 0 0
非常优雅,不是吗?
Generics
Haskell 一大令人称赞的设计是它的 generics。
"How many hacks around Go's lack of generics are you on?"
— Keith 🔰🐈🥑🏴 (@mosheroperandi) April 25, 2017
"3. Maybe 4."
"You are like baby! Watch this"https://t.co/1geXOEP3jd
h/t @bascule pic.twitter.com/83izWFCyn7
⬆️这样的事情在21世纪发生简直是不可容忍的!
回到我们刚刚的例子,我们的 Coordinate
类型只能接受两个 Integer
,如果我们想让他接受其他的类型,比如 Int
[1]、Float
甚至虚数[2]呢?
data Coordinate2 a = MkCoordinate2 a a
这里我们用到了 generics,我的理解是这是一个 Coordinate2 of a
的类型,而 a
可以是任何类型。MkCoordinate2
现在可以跟任何类型的两个参数,比如 MkCoordiante2 1 1
或者 MkCoordinate2 0.1 1.5
。
如果更进一步,我们想要它能接受两个不同类型的参数呢?
data Coordinate3 a b = MkCoordinate3 a b
很简单对吧。
再进一步,有时候可能这个坐标根本就不存在,我们想加上一个 Null
状态来表达这种情况,可以吗?
结合最上面写过的,可以这么做:
data Coordinate4 a b = MkCoordinate4 a b | Null
简直像写诗,对吧。有坐标的时候用 MkCoordinate4
,没有的时候用 Null
。他们都是 Coordinate4
类型。Polymorphism!
同样,一个函数要接受 generics 也很简单。比如我们自己定义一个 toList
函数,它接受一个参数,返回一个 list
,里面包含着我们的输入:
toList :: a -> [a]
toList i = [i]
运行起来是这样的:
*Main> toList 1
[1]
*Main> toList "hello"
["hello"]
注意它可以接受任何类型的输入,简直太优雅了对不对。