2012-09-10 28 views

Antwort

14

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.

+0

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? –

+0

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. –

+0

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' –

Verwandte Themen