Monad 定義
非正式地,monad 是元素的容器,標記為 F[_]
,包含 2 個函式:flatMap
(用於轉換此容器)和 unit
(用於建立此容器)。
常見的庫示例包括 List[T]
,Set[T]
和 Option[T]
。
正式定義
Monad M
是一個引數型別 M[T]
,有兩個操作 flatMap
和 unit
,例如:
trait M[T] {
def flatMap[U](f: T => M[U]): M[U]
}
def unit[T](x: T): M[T]
這些功能必須滿足三個法則:
- 相關性 :
(m flatMap f) flatMap g = m flatMap (x =>
f(x)flatMap g)
也就是說,如果序列不變,你可以按任何順序應用這些術語。因此,將m
應用於f
,然後將結果應用於g
將產生與將f
應用於g
相同的結果,然後將m
應用於該結果。 - 左單位 :
unit(x) flatMap f == f(x)
也就是說,x
的單位 monad 平面對映到f
相當於將f
應用於x
。 - 正確的單位 :
m flatMap unit == m
這是一個’身份’:任何與單位平面對映的單子會返回一個等同於自身的單子。
示例 :
val m = List(1, 2, 3)
def unit(x: Int): List[Int] = List(x)
def f(x: Int): List[Int] = List(x * x)
def g(x: Int): List[Int] = List(x * x * x)
val x = 1
- 相關性 :
(m flatMap f).flatMap(g) == m.flatMap(x => f(x) flatMap g) //Boolean = true
//Left side:
List(1, 4, 9).flatMap(g) // List(1, 64, 729)
//Right side:
m.flatMap(x => (x * x) * (x * x) * (x * x)) //List(1, 64, 729)
- 左單位
unit(x).flatMap(x => f(x)) == f(x)
List(1).flatMap(x => x * x) == 1 * 1
- 正確的單位
//m flatMap unit == m
m.flatMap(unit) == m
List(1, 2, 3).flatMap(x => List(x)) == List(1,2,3) //Boolean = true
標準收藏品是 Monads
大多數標準集合是 monad(List[T]
,Option[T]
)或 monad-like(Either[T]
,Future[T]
)。這些集合可以很容易地在 for
理解中組合在一起(這是編寫 flatMap
變換的等效方式):
val a = List(1, 2, 3)
val b = List(3, 4, 5)
for {
i <- a
j <- b
} yield(i * j)
以上相當於:
a flatMap {
i => b map {
j => i * j
}
}
因為 monad 保留了資料結構並且只對該結構中的元素起作用,所以我們可以使用無窮無盡的鏈 monadic 資料結構,如此處所示的 for-comprehension。