Поиск…


Определение Монады

Неофициально монада представляет собой контейнер элементов, обозначенный как F[_] , заполненный двумя функциями: 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]

Эти функции должны удовлетворять трем законам:

  1. Ассоциативность : (m flatMap f) flatMap g = m flatMap (x => f(x) flatMap g)
    То есть, если последовательность не изменяется, вы можете применять термины в любом порядке. Таким образом, применяя m к f , а затем применяя результат к g получите тот же результат, что и применение f к g , а затем примените m к этому результату.
  2. Левая единица : unit(x) flatMap f == f(x)
    То есть единичная монада x плоская карта f , эквивалентна применению f к x .
  3. Правый блок : 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
  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)

  1. Левая единица
unit(x).flatMap(x => f(x)) == f(x)
List(1).flatMap(x => x * x) == 1 * 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

Большинство стандартных коллекций являются монадами ( 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
  }
}

Поскольку монада сохраняет структуру данных и действует только на элементы внутри этой структуры, мы можем бесконечно цепные монадические структуры данных, как показано здесь для понимания.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow