Что именно делает 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 не привязан к определенному типу, а может использоваться с любым классом, реализующим определенные методы.