Come spiegato @chi, lo flatMap
di Scala è più generale di quello di Haskell >>=
. La firma completa dalla documentazione Scala è:
final def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
Questa implicita non è rilevante per questo specifico problema, in modo da poter così utilizzare la definizione più semplice:
final def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B]
C'è solo un problema, Option
non è una sottoclasse di GenTraversableOnce
, qui entra in gioco una conversione implicita. Scala definisce una conversione implicita da Option
a Iterable
che è una sottoclasse di Traversable
che è una sottoclasse di GenTraversableOnce
.
implicit def option2Iterable[A](xo: Option[A]): Iterable[A]
L'implicito è definito nell'oggetto associato di Option
.
Un modo più semplice per vedere l'implicita sul lavoro è di assegnare un Option
a un Iterable
val
:
scala> val i:Iterable[Int] = Some(1)
i: Iterable[Int] = List(1)
Scala usa alcune regole inadempienti, per selezionare List
come l'attuazione di Iterable
.
Il fatto che è possibile combinare diversi sottotipi di TraversableOnce
con le operazioni monade viene dalla implicit class
MonadOps
:
implicit class MonadOps[+A](trav: TraversableOnce[A]) {
def map[B](f: A => B): TraversableOnce[B] = trav.toIterator map f
def flatMap[B](f: A => GenTraversableOnce[B]): TraversableOnce[B] = trav.toIterator flatMap f
def withFilter(p: A => Boolean) = trav.toIterator filter p
def filter(p: A => Boolean): TraversableOnce[A] = withFilter(p)
}
Ciò aumenta ogni TraversableOnce
con i metodi di cui sopra. I sottotipi sono liberi di definire versioni più efficienti in loco, che ombreggiano le definizioni implicite. Questo è il caso di List
.
E 'solo 'List's' flatMap' o funziona per ogni tipo in Scala? – Bergi
Il 'GenTraversableOnce' è usato per tutte le" liste come "collezioni in Scala. È possibile utilizzare per es. un 'Vector' in combinazione con un' Elenco'. 'Vector (1) .flatMap (x => List (x)) == Vector (1)' o 'List (1) .flatMap (x => Vector (x)) == List (1)' – bmaderbacher
Nah, Mi chiedevo se l'uso di 'GenTraversableOnce' nella firma' flatMap' è una generalizzazione specifica per gli elenchi o che funziona in tutte le monadi (tipi con un metodo 'flatMap'?)? – Bergi