Mit zwei Monaden ist beides nicht genug (für M
) und mehr als genug (für N
) -die bis fügt nicht genug, natürlich, aber wenn M
eine Traverse
Instanz hat und N
hat eine Applicative
Instanz, können Sie Verwenden Sie sequence
. Zum Beispiel:
import scalaz._, Scalaz._
def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence
Dies hat die Semantik, die Sie wollen. Beachten Sie, dass ich List
anstelle von Seq
verwende, da Scalaz 7 nicht mehr die erforderliche Traverse
Instanz für Seq
bereitstellt (obwohl Sie problemlos Ihre eigenen schreiben könnten).
Wie Sie bemerkt haben, kompilieren folgendes nicht:
List(Some(1), Some(45)).sequence
Obwohl es in Ordnung, wenn Sie einen None
dort werfen:
scala> List(Some(1), None, Some(45)).sequence
res0: Option[List[Int]] = None
Dies liegt daran, der abgeleiteten Typ List(Some(1), Some(45))
wird List[Some[Int]]
sein, und wir haben keine Applicative
Instanz für Some
.
Scalaz bietet eine praktische some
Methode, wie Some.apply
funktioniert aber gibt Ihnen etwas, das bereits als Option
eingegeben ist, so können Sie schreiben folgendes:
scala> List(some(1), some(45)).sequence
res1: Option[List[Int]] = Some(List(1, 45))
keine zusätzliche Eingabe erforderlich.
In REPL mit Scalaz 7 schlägt es fehl, weil es eine Traverse-Klasseninstanz für Seq nicht finden kann. Vielleicht sollte ich noch etwas importieren? –
Sie können "List" anstelle von "Seq" verwenden oder eine eigene Instanz für "Seq" bereitstellen. Ich bin nicht sicher, warum die "Seq" -Instanzen in 7 verschwunden sind. –
Danke, es funktioniert! Aber ich bin frustriert mit seinem Verhalten: außer dem 'Seq'-Problem gibt es noch einen anderen, bei dem Sie den Typ explizit angeben müssen:' val xs = List (Some (1), Some (45)); (xs: Liste [Option [Int]]). Sequenz' –