Qu'est-ce qui fait exactement une Option monade dans Scala?
je sais ce que les monades sont et comment les utiliser. Ce que je ne comprends pas c'est fait, disons,Option
une monade?
En Haskell une monade Maybe
est un monad parce qu'il est instancié de Monad
classe (qui a au moins 2 fonctions nécessaires return
et bind
qui fait de classe Monad
, en effet, une monade).
mais à Scala nous avons ceci:
sealed abstract class Option[+A] extends Product with Serializable { ... }
trait Product extends Any with Equals { ... }
rien de lié à une monade.
Si je crée mon propre classe Scala, ce sera une sorte de monade par défaut? Pourquoi pas?
3 réponses
Monad
est un concept, une interface abstraite qui définit simplement une manière de composer de données.
Option
supporte la composition via flatMap
, et c'est à peu près tout ce dont on a besoin pour porter le "badge monad".
d'un point de vue théorique, il devrait aussi:
- soutien
unit
(return
, en termes de Haskell) pour créer une monade à partir d'une valeur nue, ce qui dans le cas deOption
est leSome
constructeur - respecter le monadique lois
mais cela N'est pas strictement appliqué par Scala.
les monades en scala sont un concept beaucoup plus souple que dans Haskell, et l'approche est plus pratique. La seule chose pour laquelle les monades sont pertinentes, du point de vue de la langue, est la capacité d'être utilisé dans une compréhension.
flatMap
est une exigence de base, et vous pouvez éventuellement donner map
, withFilter
et foreach
.
cependant, il n'y a pas de stricte conformité à un Monad
typeclass, comme dans Haskell.
voici un exemple: définissons notre propre monad.
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
}
Comme vous le voyez, nous ne sommes qu'à la mise en œuvre de map
et flatMap
(Eh bien, et toString
comme marchandise).
Félicitations, nous avons une monade! Essayons ceci:
scala> for {
a <- new MyMonad(2)
b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5
Nice! Nous ne faisons pas de filtrage, donc nous n'avons pas besoin d'implémenter withFilter
. Également puisque nous donnons une valeur, nous n'avons pas besoin deforeach
soit. Fondamentalement, vous mettre en œuvre tout ce que vous souhaitez soutenir, sans exigences strictes. Si vous essayez de filtrer dans une compréhension et vous n'avez pas implémenté withFilter
, vous obtiendrez simplement une erreur de compilation.
Tout ce qui (partiellement) met en œuvre, par le biais de la dactylographie du canard, le FilterMonadic
trait est considéré comme une monade dans Scala. C'est différent de la façon dont les monades sont représentées dans Haskell, ou le Monad
typeclass dans scalaz. Toutefois, afin de bénéficier de l' for
compréhension sucre syntaxique en Scala, un objet doit exposer certaines des méthodes définies dans le FilterMonadic
trait de caractère.
aussi, à Scala, l'équivalent du Haskell return
la fonction est l' yield
mot-clé utilisé pour produire des valeurs à partir d'un for
compréhension. Le desugaring de yield
est un appel à map
méthode de la "monade".
la façon dont je l'ai dit est qu'il y a une distinction émergente entre les monades comme un modèle de conception vs abstraction de première classe. Haskell a ce dernier, sous la forme de Monad
classe de type. Mais si vous avez un type qui a (ou peut mettre en œuvre) les monadique opérations et obéit aux lois, c'est une monade.
de nos jours, vous pouvez voir les monades comme un modèle de conception dans les bibliothèques de Java 8. Optional
et of méthode qui correspond à Haskell return
et flatMap
méthode. Il n'existe cependant aucun Monad
type.
quelque part entre les deux vous avez également l'approche "duck-typed", comme la réponse de Ionuț G. Stan appelle. C# A ceci aussi bien-la syntaxe LINQ n'est pas liée à un type spécifique, mais elle peut être utilisée avec n'importe quelle classe qui implémente certaines méthodes.