Что именно делает Option монадой в Scala?

Я знаю, что такое монады и как их использовать. Чего я не понимаю, так это что делает, скажем, Option монада?

в Haskell монада Maybe является монадой, потому что она создается из Monad класс (который имеет по крайней мере 2 необходимые функции return и bind что делает класс Monad, действительно, монада).

но в Scala у нас есть это:

sealed abstract class Option[+A] extends Product with Serializable { ... }
trait Product extends Any with Equals { ... }

ничего, связанного с монадой.

если я создам свой собственный класс в Scala, будет ли он монадой по умолчанию? Почему бы и нет?

3 ответов


Monad - это концепция, абстрактный интерфейс, если хотите, который просто определяет способ составления данных.

Option поддерживает композицию через flatMap, и это почти все, что нужно, чтобы носить значок "монада".

С теоретической точки зрения, следует также:

  • поддержка a unit операция (return, в терминах Haskell), чтобы создать монаду из голого значения, которое в случае Option - это Some конструктор
  • уважаю законы монад

но это не строго соблюдается Scala.

монады в scala-гораздо более свободная концепция, чем в Haskell, и подход более практичен. Единственное, для чего монады актуальны, с точки зрения языка, - это способность использоваться для понимания.

flatMap является основным требованием, и вы можете дополнительно обеспечить map, withFilter и foreach.

однако нет такой вещи, как строгое соответствие Monad typeclass, как в Haskell.

вот пример: давайте определим нашу собственную монаду.

class MyMonad[A](value: A) {
  def map[B](f: A => B) = new MyMonad(f(value))
  def flatMap[B](f: A => MyMonad[B]) = f(value)
  override def toString = value.toString
}

как вы видите, мы только реализуем map и flatMap (ну и toString как товар). Поздравляю, у нас есть монада! Давайте попробуем:

scala> for {
  a <- new MyMonad(2)
  b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5

славный! Мы не делаем никакой фильтрации, поэтому нам не нужно реализовывать withFilter. Также поскольку мы получаем ценность, нам не нужно foreach либо. В основном вы реализуете все, что хотите поддержать, без строгих требований. Если вы попытаетесь отфильтровать для понимания, и вы не реализовали withFilter, вы просто получите ошибку времени компиляции.


все, что (частично) реализует, через утиный ввод,FilterMonadic признак считается монадой в Scala. Это отличается от того, как монады представлены в Haskell, или Monad typeclass в scalaz. Однако, чтобы извлечь выгоду из for понимание синтаксического сахара в Scala, объект должен выставить некоторые из методов, определенных в FilterMonadic черта.

также, в Scala, эквивалент Haskell return функция yield ключевое слово, используемое для получения значения из for понимания. В результате обессахаривания из yield звонок map метод "монада".


как я бы выразился, есть возникающее различие между монадами как шаблон и первый-класс абстракция. У Хаскелла есть последнее, в форме Monad тип класса. Но если у вас есть тип, который имеет (или может реализовать) монадические операции и подчиняется законам, это тоже монада.

в эти дни вы можете видеть монады как шаблон дизайна в библиотеках Java 8. The Optional и Stream типы в Java 8 поставляются с static of метод, соответствующий Haskell return и flatMap метод. Однако нет Monad тип.

где-то между вами также есть подход "утка-типизированный", как призывает ответ Ionuț G. Stan. C# также имеет это-синтаксис LINQ не привязан к определенному типу, а может использоваться с любым классом, реализующим определенные методы.