昨天我們說到可以使用 tuple (Double, Double, Double)
用三個double來表示三角形的三邊長。
但我們使用 tuple 來描述的話我們是根據位置來決定這個 field 的定義,所以假設我們是要來描述三角形 t
那可能會是長這樣
t = (3.0,4.0,5.0)
我們沒辦法直覺地想說哪個值代表哪一個邊,而且如果今天剛好出現一個也是 (Double, Double, Double)
的數值時我也無法確定這個 tuple 到底是指什麼東西,像是如果今天我要描述一個三維座標系統上的某一個點也許也會是 (Double, Double, Double)
。
那有其他方法可以幫助我們解決這個問題嗎?沒錯,就是 Algebraic Data Types。
所謂 product type 簡單來說就是多個型態結合在一起的型別,我們要定義一個 data type 需要使用一個新的語法 data
data Triangle = Triangle Double Double Double deriving (Show,Eq)
data Point = Point Double Double Double deriving (Show,Eq)
以 Triangle
為例,=
左邊就是我們要定義一個 data type 的語法 data typeName
,=
右邊就是 value constructor (其實就是來說明這個 value 是用何種 type 構建的) 及這個建構這個data type 所需要的 type
至於 deriving (Show,Eq)
現在我只要知道他是能讓我將這個 data type 也屬於 Show
及 Eq
type class 中的一員方便我們輸出結果及比較用。
使用起來會像是
t0 = Triangle 1.0 2.0 2.0
t1 = Triangle 1.0 2.0 2.0
t2 = Triangle 2.0 2.0 3.0
t0 -- Triangle 1.0 2.0 2.0
t1 -- Triangle 1.0 2.0 2.0
t2 -- Triangle 2.0 2.0 3.0
t0 == t1 -- True
t0 == t2 -- False
p0 = Point 1.0 2.0 2.0
p1 = Point 1.0 2.0 2.0
p1 = Point 2.0 2.0 3.0
p0 -- Point 1.0 2.0 2.0
p1 -- Point 1.0 2.0 2.0
p2 -- Point 2.0 2.0 3.0
p0 == p1 -- True
p0 == p2 -- False
那如果我們拿 p0
與 t0
比較呢?
p0 == t0
<interactive>:174:7: error:
• Couldn't match expected type ‘Point’ with actual type ‘Triangle’
• In the second argument of ‘(==)’, namely ‘t0’
In the expression: p0 == t0
In an equation for ‘it’: it = p0 == t0
編譯器會告訴我們 Point
無法match 到 Triangle
,雖然就數值上他們都是 1.0 2.0 3.0
但是因為他們的 type 不一樣,這也是 data type 的好處因為如果換作是 tuple 的話,他們會是相等的
(1.0,1.0) == (1.0,1.0) -- True
之所以 product type 叫做 product type 是因為這個 type 的可能性剛好是各個 field 的 type 的可能性相乘的結果
data Foo = Foo Bool Bool
Bool
只有 True
或者 False
所以 Foo
窮舉後只會有 2*2 的可能性
Foo True True
Foo True False
Foo False False
Foo False True
雖然上面的範例可以解決我們就算數值一樣也不能代表兩個變數是一樣的,所以 Haskell 提供了 record syntax
data Triangle' = Triangle {
ab :: Double,
bc :: Double,
ca :: Double
} deriving (Show)
let t0' = Triangle' 1.0 2.0 3.0
print $ Triangle'
-- Triangle' {ab = 1.0, bc = 2.0, ca = 3.0}
這樣我們就能很簡單的看出這個 data type 的各項代表的意義是什麼,稍微提醒一下就算我們使用了 record syntax 其實也是屬於 product type 哦。
今天的程式碼:https://github.com/toddLiao469469/30days-for-haskell