Подтвердить что ты не робот

Что именно делает вариант монадой в 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, это будет монада по умолчанию? Почему бы и нет?

4b9b3361

Ответ 1

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

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

С теоретической точки зрения это также должно быть:

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

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

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

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

Однако нет такой вещи, как строгое соответствие классу Monad, например, в 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, вы просто получите ошибку времени компиляции.

Ответ 2

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

Кроме того, в Scala эквивалент функции Haskell return является ключевым словом yield, используемым для создания значений из понимания for. Desugaring yield - это вызов метода map "монады".

Ответ 3

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

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

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