¿Cómo convertir A ] a B ] si A y B son mónadas?

Estoy buscando una solución más general que explote las mónadas (y monoides posiblemente) para lograr lo mismo que if( xs.contains(None) ) None else Some(xs.flatten) hace para xs de tipo Seq[Option[A]]

¿Cómo puedo hacer eso con Scalaz? Siento que me falta algo evidente.

Tener dos mónadas no es suficiente (para M ) y más que suficiente (para N ), que no es suficiente, por supuesto, pero si M tiene una instancia de Traverse y N tiene una instancia Applicative , puede usar sequence . Por ejemplo:

 import scalaz._, Scalaz._ def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence 

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


Como habrás notado, lo siguiente no se comstackrá:

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

Aunque está bien si lanzas una None allí:

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

Esto se debe a que el tipo inferido de List(Some(1), Some(45)) será List[Some[Int]] , y no tenemos una instancia Applicative para Some .

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

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

No es necesario escribir más.