從今天開始要進入 Part 3 啦!Part 3 主要是 functional programming 下更高層的抽象,也就是說把之前各種主題下常看到的模式概念整合起來、抽象出來成 library,節省重複的程式碼設計,之後的幾天目標就是介紹這些抽象概念,訓練你辨識模式,然後介紹一下各種模式的優點。
Monoid 是我們將要介紹的第一個純粹的代數資料結構,僅由代數性質定義。
Monoid 來自於數學,在 Category Theory 中,它意思為一個 category 只有一個 object,數學上的定義在這裡不太重要(詳細的說明可以看 維基百科)。
首先我們來看一下連續字串的代數性質,foo + bar
會等於 foobar
,而空字串 ""
在這裡面被稱為 identity element (單位元素),如果我們用 (s + "")
或 ("" + s)
,其結果都會是 s,
進一步來看,如果我們合併 3 個字串 (r + s + t)
,其算子是具有 Associative property (結合律) 性質的,也就是說不管我們怎麼用括號分隔,((r + s) + t)
或 (r + (s + t))
,其結果都相同,
相同的定律對數字也適用,例如 (x + y) + z
始終會等於 x + (y + z)
,它的單位元素是 0,
而 &&
或 ||
同樣也具有結合律;
這種型態的代數性就稱為 Monoid,而 Monoid 定律會由下列項目組成:
combine
,它接受 2 個型態為 A 的參數,然後合併它們做為結果,combine(combine(x, y), z) == combine(x, combine(y, z))
,其 x, y, z 的型態皆為 A。empty
的值,它是單位元素並能滿足以下操作,combine(x, empty) == x
和 combine(empty, x) == x
,x 的型態為 A。把這些用 Scala 表示的話程式長這樣,
trait Monoid[A]:
def combine(a1: A, a2: A): A
def empty: A
用字串來實作的話長這樣。
val stringMonoid: Monoid[String] = new:
def combine(a1: String, a2: String) = a1 + a2
val empty = ""
無參數的 function 可以在實作時用 val 實作。
Exercise D22-1
來實作加、乘、AND 和 OR 操作吧!
val intAddition: Monoid[Int]
val intMultiplication: Monoid[Int]
val booleanAnd: Monoid[Boolean]
val booleanOr: Monoid[Boolean]
Exercise D22-2
用 Option 來實作 Monoid 介面。
def optionMonoid[A]: Monoid[Option[A]]
Monoid 就是能用一個相同型態二元操作 function 滿足結合律且有著單位元素的東西啦!