Scala Language
Monades
Recherche…
Monad Définition
De manière informelle, une monade est un conteneur d'éléments, notés F[_]
, contenant 2 fonctions: flatMap
(pour transformer ce conteneur) et unit
(pour créer ce conteneur).
Les exemples courants de bibliothèque incluent List[T]
, Set[T]
et Option[T]
.
Définition formelle
Monad M
est un type paramétrique M[T]
avec deux opérations flatMap
et unit
, telles que:
trait M[T] {
def flatMap[U](f: T => M[U]): M[U]
}
def unit[T](x: T): M[T]
Ces fonctions doivent satisfaire à trois lois:
- Associativité :
(m flatMap f) flatMap g = m flatMap (x => f(x) flatMap g)
En d'autres termes, si la séquence reste inchangée, vous pouvez appliquer les termes dans n'importe quel ordre. Ainsi, appliquerm
àf
, puis appliquer le résultat àg
donnera le même résultat que si l'on appliquaitf
àg
, puis appliquerm
à ce résultat. - Unité de gauche :
unit(x) flatMap f == f(x)
C'est-à-dire que la monade d'unité dex
cartographiée à traversf
équivaut à appliquerf
àx
. - Unité droite :
m flatMap unit == m
C'est une «identité»: toute monade à plat contre une unité retournera une monade équivalente à elle-même.
Exemple :
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é de gauche
unit(x).flatMap(x => f(x)) == f(x)
List(1).flatMap(x => x * x) == 1 * 1
- Unité droite
//m flatMap unit == m
m.flatMap(unit) == m
List(1, 2, 3).flatMap(x => List(x)) == List(1,2,3) //Boolean = true
Les collections standard sont des monades
La plupart des collections standard sont des monades ( List[T]
, Option[T]
) ou des monades (E Either[T]
, Future[T]
). Ces collections peuvent être facilement combinées entre elles for
compréhensions (qui sont une manière équivalente d'écrire des transformations flatMap
):
val a = List(1, 2, 3)
val b = List(3, 4, 5)
for {
i <- a
j <- b
} yield(i * j)
Ce qui précède est équivalent à:
a flatMap {
i => b map {
j => i * j
}
}
Étant donné qu'une monade préserve la structure de données et n'agit que sur les éléments de cette structure, nous pouvons sans fin mettre en place des structures de données monadiques, comme illustré ici pour une compréhension.