Scala Language
monadi
Ricerca…
Definizione di Monade
Informalmente, una monade è un contenitore di elementi, indicato come F[_]
, ricco di 2 funzioni: flatMap
(per trasformare questo contenitore) e unit
(per creare questo contenitore).
Esempi di librerie comuni includono List[T]
, Set[T]
e Option[T]
.
Definizione formale
Monad M
è un tipo parametrico M[T]
con due operazioni flatMap
e unit
, come ad esempio:
trait M[T] {
def flatMap[U](f: T => M[U]): M[U]
}
def unit[T](x: T): M[T]
Queste funzioni devono soddisfare tre leggi:
- Associatività :
(m flatMap f) flatMap g = m flatMap (x => f(x) flatMap g)
Cioè, se la sequenza è invariata puoi applicare i termini in qualsiasi ordine. Quindi, applicandom
f
, e quindi applicando il risultato ag
otterrà lo stesso risultato dell'applicazione dif
ag
applicandom
a quel risultato. - Unità sinistra :
unit(x) flatMap f == f(x)
Cioè, l'unità monad dix
flat-mapped suf
equivale a applicaref
ax
. - Unità destra :
m flatMap unit == m
Questa è una "identità": qualsiasi unità monad flat-mapped restituirà una monade equivalente a se stessa.
Esempio :
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
- Associatività :
(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à sinistra
unit(x).flatMap(x => f(x)) == f(x)
List(1).flatMap(x => x * x) == 1 * 1
- Unità giusta
//m flatMap unit == m
m.flatMap(unit) == m
List(1, 2, 3).flatMap(x => List(x)) == List(1,2,3) //Boolean = true
Le collezioni standard sono Monade
La maggior parte delle raccolte standard sono monade ( List[T]
, Option[T]
) o monad ( Either[T]
, Future[T]
). Queste raccolte possono essere facilmente combinate insieme for
comprensione (che è un modo equivalente di scrivere trasformazioni flatMap
):
val a = List(1, 2, 3)
val b = List(3, 4, 5)
for {
i <- a
j <- b
} yield(i * j)
Quanto sopra è equivalente a:
a flatMap {
i => b map {
j => i * j
}
}
Poiché una monade conserva la struttura dei dati e agisce solo sugli elementi all'interno di quella struttura, possiamo disporre di infinite strutture monadiche a catena, come mostrato qui in una comprensione preliminare.