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 M
Traverse
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.
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? –
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. –
¡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' –