Szukaj…


Definicja Monady

Nieformalnie monada jest kontenerem elementów oznaczonym jako F[_] i zawiera 2 funkcje: flatMap (do przekształcenia tego kontenera) i unit (do utworzenia tego kontenera).

Typowe przykłady bibliotek obejmują List[T] , Set[T] i Option[T] .

Formalna definicja

Monada M to parametryczny typ M[T] z dwiema operacjami flatMap i unit , takimi jak:

trait M[T] {
  def flatMap[U](f: T => M[U]): M[U]
}

def unit[T](x: T): M[T]

Funkcje te muszą spełniać trzy prawa:

  1. Łączność: (m flatMap f) flatMap g = m flatMap (x => f(x) flatMap g)
    Oznacza to, że jeśli sekwencja nie ulegnie zmianie, możesz zastosować warunki w dowolnej kolejności. Zatem zastosowanie m do f , a następnie zastosowanie wyniku do g da taki sam wynik, jak zastosowanie f do g , a następnie zastosowanie m do tego wyniku.
  2. Lewa jednostka : unit(x) flatMap f == f(x)
    Oznacza to, że monada jednostkowa x płasko zmapowana w poprzek f jest równoważna zastosowaniu f do x .
  3. Prawa jednostka : m flatMap unit == m
    Jest to „tożsamość”: każda monada płasko odwzorowana przeciwko jednostce zwróci monadę odpowiadającą jej samej.

Przykład :

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
  1. Stowarzyszenie :
(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)

  1. Lewa jednostka
unit(x).flatMap(x => f(x)) == f(x)
List(1).flatMap(x => x * x) == 1 * 1

  1. Właściwa jednostka
//m flatMap unit == m
m.flatMap(unit) == m
List(1, 2, 3).flatMap(x => List(x)) == List(1,2,3) //Boolean = true

Kolekcje standardowe to Monady

Większość standardowych kolekcji to monady ( List[T] , Option[T] ) lub monadopodobne ( Either[T] , Future[T] ). Te zbiory można łatwo łączyć ze sobą w for zrozumienia (które są równoważnym sposobem pisania transformacji flatMap ):

val a = List(1, 2, 3)
val b = List(3, 4, 5)
for {
  i <- a
  j <- b
} yield(i * j)

Powyższe jest równoważne z:

a flatMap {
  i => b map {
    j => i * j
  }
}

Ponieważ monada zachowuje strukturę danych i działa tylko na elementy w tej strukturze, możemy w nieskończoność łańcuchować monadyczne struktury danych, jak pokazano tutaj dla zrozumienia.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow