2012-09-10 5 views

risposta

14

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.

+0

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

+0

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

+0

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