讓我們重新回顧一下 typeclass 是什麼,它類似於其他語言中的介面(interface)。Typeclass 提供了一種定義一組類別所需具備的行為和特性的方式,就像 Eq
這個 typeclass 提供了比較是否相等的行為。
typeclass 是通過函數來描述這些行為的,所以當我們將一個 type 定義為這個 typeclass 的實例(instance)時,代表這個 type 具備了 typeclass 所定義的這些函數的實作,可以使用這些函數來操作該型別的值。
雖然我們一直提到 class 、instance 之類的詞,但他們跟你在其他語言所得知 class 、instance 「完全沒有關係」。
我們可以先來看 Eq
是怎麼被定義的
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
{-# MINIMAL (==) | (/=) #-}
首先我們看到了新語法 class Eq a where
代表定義一個 typeclass 叫做 Eq
然後 a
則是 type parameters 也就代表我們在實作 class 的 instance 時的 type 。
那接下來我們來為 Eq 定義一個新的 instance,首先我們先定義一個新的 data type
data Color = Red | Green | Blue
在我們不使用 deriving(Eq)
的情況下我們就需要手動建造 Eq
的 instance
instance Eq Color where
Red == Red = True
Green == Green = True
Blue == Blue = True
_ == _ = False
這點可以看到我們用了一個新語法 instance
然後接上我們要實作的 typeclass 及 type 。
還記得我們前面 Eq
的定義嗎,我們至少需要實作 ==
,所以我們這邊就將 Color
對於 ==
的實作加上去。
這邊依然是使用 pattern matching 來實作,當我們配對到 Red == Red
時那就是 True
其他以此類推直到最後 _ == _
也就是當任意兩種進行 ==
運算都會是 False
也就是結果來說只要不是匹配到前三種的情況就一定會是 False
。
然後我們也可以順便實作 Show
的 instance
instance Show Color where
show Red = "Color: Red"
show Green = "Color: Green"
show Blue = "Color: Blue"
如果我們直接使用deriving(Show)
在這個例子就會把 value constructor 直接轉成 String
,但我們現在既然是自己實作 instance 我們就可以自己改變一下想輸出的字串,這邊一樣是用 pattern matching 來實作,就是匹配到哪種value constructor 就回傳對應的字串。
運行起來會像是這樣
print $ Red == Red -- True
print $ Red == Green -- False
print $ Red == Blue -- False
print $ Green == Green -- True
print $ Green == Blue -- False
print $ Blue == Blue -- True
print $ show Red -- "Color: Red"
print $ show Green -- "Color: Green"
print $ show Blue -- "Color: Blue"
今天我們又說回了 typeclass ,我覺得這是 Haskell 中相對困難且抽象的環節,明天我們將繼續深入typeclass
中秋連假還在寫文章真的好累
今天的程式碼:https://github.com/toddLiao469469/30days-for-haskell