iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Software Development

Haskell 從入門到放棄系列 第 14

[Haskell 從入門到放棄] Day 14 - Algebraic Data Types (1)

  • 分享至 

  • xImage
  •  

昨天我們說到可以使用 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

所謂 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 也屬於 ShowEq 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

那如果我們拿 p0t0 比較呢?

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

Record Syntax

雖然上面的範例可以解決我們就算數值一樣也不能代表兩個變數是一樣的,所以 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


上一篇
[Haskell 從入門到放棄] Day13 - Tuple
下一篇
[Haskell 從入門到放棄] Day 15 - Algebraic Data Types (2)
系列文
Haskell 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言