Scala Language
monader
Sök…
Monad Definition
Informellt är en monad en behållare med element, noterade som F[_]
, packade med två funktioner: flatMap
(för att transformera denna behållare) och unit
(för att skapa denna behållare).
Vanliga biblioteksexempel inkluderar List[T]
, Set[T]
och Option[T]
.
Formell definition
Monad M
är en parametrisk typ M[T]
med två operationer flatMap
och unit
, såsom:
trait M[T] {
def flatMap[U](f: T => M[U]): M[U]
}
def unit[T](x: T): M[T]
Dessa funktioner måste uppfylla tre lagar:
- Associativitet :
(m flatMap f) flatMap g = m flatMap (x => f(x) flatMap g)
Det vill säga, om sekvensen är oförändrad kan du tillämpa villkoren i vilken ordning som helst. Således applicerarm
tillf
, och sedan applicerar resultatet påg
ger samma resultat som applicerarf
tillg
, och sedan applicerarm
på det resultatet. - Vänster enhet :
unit(x) flatMap f == f(x)
Det vill säga, enhetsmonaden förx
platt-mappad överf
motsvarar tillämpningen avf
tillx
. - Höger enhet :
m flatMap unit == m
Detta är en 'identitet': varje monad som är platt-mappad mot enhet kommer att returnera en monad motsvarande sig själv.
Exempel :
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
- Associativitet :
(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)
- Vänster enhet
unit(x).flatMap(x => f(x)) == f(x)
List(1).flatMap(x => x * x) == 1 * 1
- Höger enhet
//m flatMap unit == m
m.flatMap(unit) == m
List(1, 2, 3).flatMap(x => List(x)) == List(1,2,3) //Boolean = true
Standardsamlingar är monader
De flesta av standardsamlingarna är monader ( List[T]
, Option[T]
) eller monadliknande ( Either[T]
, Future[T]
). Dessa samlingar kan enkelt kombineras inom for
förstå (som är ett likvärdigt sätt att skriva flatMap
transformationer):
val a = List(1, 2, 3)
val b = List(3, 4, 5)
for {
i <- a
j <- b
} yield(i * j)
Ovanstående motsvarar:
a flatMap {
i => b map {
j => i * j
}
}
Eftersom en monad bevarar datastrukturen och endast agerar på elementen i den strukturen, kan vi oändliga monadiska datastrukturer, som visas här i en förståelse.