Avere due monadi è sia non è sufficiente (per M
) e più che sufficiente (per N
) -che aggiunge fino a non abbastanza, naturalmente, ma se M
ha un'istanza Traverse
e N
ha un'istanza Applicative
, è possibile utilizzare sequence
. Ad esempio:
import scalaz._, Scalaz._
def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence
Questo ha la semantica desiderata. Si noti che sto utilizzando List
anziché Seq
, poiché Scalaz 7 non fornisce più l'istanza Traverse
necessaria per Seq
(anche se si potrebbe scrivere facilmente la propria).
Come avete notato, quanto segue non compilare:
List(Some(1), Some(45)).sequence
Anche se è bene se si lancia una None
in là:
scala> List(Some(1), None, Some(45)).sequence
res0: Option[List[Int]] = None
Questo perché il dedotto il tipo di List(Some(1), Some(45))
sarà List[Some[Int]]
e non abbiamo un'istanza Applicative
per Some
.
Scalaz fornisce un some
metodo pratico che funziona come Some.apply
ma ti dà qualcosa che è già digitato come Option
, in modo da poter scrivere il seguente:
scala> List(some(1), some(45)).sequence
res1: Option[List[Int]] = Some(List(1, 45))
Nessuna battitura a macchina in più necessaria.
fonte
2012-09-10 20:25:17
In REPL con Scalaz 7 non riesce perché non riesce a trovare un'istanza di classe di esempio Traverse per Seq. Forse c'è qualcos'altro che dovrei importare? –
Puoi usare 'List' invece di' Seq', o fornire la tua istanza per 'Seq'-Non sono sicuro del motivo per cui le istanze di' Seq' sono scomparse in 7. –
Grazie, ha funzionato! Ma sono frustrato dal suo comportamento: oltre al problema "Seq' ce n'è un altro che richiede di specificare esplicitamente il tipo:' val xs = List (Some (1), Some (45)); (xs: List [Option [Int]]). sequence' –