2012-09-10 39 views

Respuesta

14

Tener dos mónadas es a la vez no es suficiente (por M) y más que suficiente (por N) -que se suma a poco, por supuesto, pero si tiene una instancia de MTraverse y N tiene una instancia Applicative, puede use sequence. Por ejemplo:

import scalaz._, Scalaz._ 

def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence 

Tiene la semántica que desea. Tenga en cuenta que estoy usando List en lugar de Seq, ya que Scalaz 7 ya no proporciona la instancia necesaria Traverse para Seq (aunque podría escribir fácilmente la suya).


Como se ha notado, los siguientes no se compilará:

List(Some(1), Some(45)).sequence 

Aunque está bien si se lanza un None allí:

scala> List(Some(1), None, Some(45)).sequence 
res0: Option[List[Int]] = None 

Esto es debido a que la inferida tipo de List(Some(1), Some(45)) será List[Some[Int]], y no tenemos una instancia Applicative para Some.

Scalaz proporciona un método práctico some que funciona como Some.apply pero le da algo que ya se ha escrito como un Option, por lo que puede escribir lo siguiente:

scala> List(some(1), some(45)).sequence 
res1: Option[List[Int]] = Some(List(1, 45)) 

Sin tipificación adicional necesario.

+0

En REPL con Scalaz 7 falla porque no se puede encontrar una instancia de clase de clase Traverse para Seq. Tal vez hay algo más que debería importar? –

+0

Puede usar 'List' en lugar de' Seq', o proporcionar su propia instancia para 'Seq'-No estoy seguro de por qué las instancias' Seq' han desaparecido en 7. –

+0

¡Gracias, lo he conseguido! Pero estoy frustrado con su comportamiento: además del problema 'Seq' hay otro que requiere que especifiques el tipo explícitamente: 'val xs = List (Some (1), Some (45)); (xs: Lista [Opción [Int]]). secuencia' –

Cuestiones relacionadas