Ответ 1
Недостаточно наличия двух монад (для M
) и более чем достаточно (для N
) - это, конечно, не достаточно, но если M
имеет экземпляр Traverse
и N
имеет экземпляр Applicative
, вы можете использовать sequence
. Например:
import scalaz._, Scalaz._
def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence
Это семантика, которую вы хотите. Обратите внимание, что я использую List
вместо Seq
, так как Scalaz 7 больше не предоставляет необходимый экземпляр Traverse
для Seq
(хотя вы можете легко написать свой собственный).
Как вы заметили, следующее не будет компилироваться:
List(Some(1), Some(45)).sequence
Хотя это прекрасно, если вы выбрали None
там:
scala> List(Some(1), None, Some(45)).sequence
res0: Option[List[Int]] = None
Это потому, что выводимый тип List(Some(1), Some(45))
будет List[Some[Int]]
, и у нас нет экземпляра Applicative
для Some
.
Scalaz предлагает удобный Some
метод, который работает как Some.apply
, но дает вам то, что уже было напечатано как Option
, поэтому вы можете написать следующее:
scala> List(some(1), some(45)).sequence
res1: Option[List[Int]] = Some(List(1, 45))
Не требуется дополнительная набрав.