iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
Software Development

Haskell 從入門到放棄系列 第 22

[Haskell 從入門到放棄] Day 22 - Monoid (2)

  • 分享至 

  • xImage
  •  

Maybe

在 Haskell 中 Maybe a 也是能具有 Monoid 特性的。

instance Monoid a => Monoid (Maybe a) where
  mempty = Nothing
  Nothing `mappend` m = m
  m `mappend` Nothing = m
  Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)

首先我們先注意一下我們這裡是用 instance Monoid a => Monoid (Maybe a) 而不是 Monoid Maybe ,因為在定義 Monoid 的 instance 時是需要一個明確的 type ,所以這裡就會是使用 Maybe a 。 也就代表當 aMonoidMaybe a 才會是 Monoid

其實 list 在實作 Monoid 時也是如此,只是 list 所裝的元素 type 跟他是否有辦法實作出 Monoid 沒有關係,但 Monoid 依然會需要是一個明確的 type 所以才會是這個 instance Monoid [a] 不用型別約束的樣子 。

剩下就是 mempty 是用 Nothing ,以及如果兩個 Just 進行 mappend 運算時是將 m1m2 進行 mappend 運算在用 Just wrap 起來

Nothing `mappend` Just "1"  -- Just "1"
Just "1" `mappend` Nothing  -- Just "1"

Just (Sum 1) `mappend` Just (Sum 2) -- Just (Sum {getSum = 3})
Just [1] `mappend` Just [2,3] -- Just [1,2,3]

那這麼做的好處是什麼?我想比較大的用處是在我們處理複數個 Maybe 時,我們可以簡單地合併這些 Maybe 而不用擔心它是 Nothing 還是 Just a

講回 Semigroup

其實 semigroup 是比 monoid 更加基礎的概念,他就只是定義了遵守結合律的二元函數運算。

其實所謂的二元函數運算就是 Magma 這個數學概念,它定義一個集合及運算 (S,*) ,而 S 為一非空集合,* 是一個二元運算它將集合中兩個元素進行運算後會映射到集合中其中一個元素。 像是加法就是一種 Magma ,它可以接受兩個實數相加後會映射會原本的實數集合裡。

class Semigroup a where
  (<>) :: a -> a -> a

這邊可以看到我們只定義了一個 function <> 他就只是一個接受兩個 type 為 a 的值並回傳一個type 為 a 的值,而當然他要遵守結合律才能稱為 semigroup 。

所以我們可以得出幾個小結論

  1. 每一個 Monoid 都是 Semigroup
  2. Semigroup 就是定義了元素間組合的行為。
  3. Monoid 多了 identity 這個規則也因此 Monoid 對於空值的處理會更加簡單。

寫到這裡開始覺得當在 Haskell 遇到愈抽象的概念表示它愈接近數學上的定義了,總而言之不管 MonoidSemigroupFunctor 都是藉由 typeclass 來定義我們該符合哪些行為及特性來符合數學上的某些性質,而這些性質都是為了能我們的程式碼更加的抽象(或者該說泛用)。


上一篇
[Haskell 從入門到放棄] Day 21 - Monoid (1)
下一篇
[Haskell 從入門到放棄] Day 23 - Monad (1)
系列文
Haskell 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言