Имея
(Some(1), Some(2))
Я ожидаю получить
Some((1, 2))
и имея
(Some(1), None)
Я ожидаю получить
None
Имея
(Some(1), Some(2))
Я ожидаю получить
Some((1, 2))
и имея
(Some(1), None)
Я ожидаю получить
None
Вы можете использовать тот факт, что Scalaz 7 предоставляет экземпляр Bitraverse
для кортежей, а затем последовательность как обычно (но с bisequence
вместо sequence
):
scala> import scalaz._, std.option._, std.tuple._, syntax.bitraverse._
import scalaz._
import std.option._
import std.tuple._
import syntax.bitraverse._
scala> val p: (Option[Int], Option[String]) = (Some(1), Some("a"))
p: (Option[Int], Option[String]) = (Some(1),Some(a))
scala> p.bisequence[Option, Int, String]
res0: Option[(Int, String)] = Some((1,a))
К сожалению, Scalaz 7 в настоящее время нуждается в аннотации типа.
В комментарии Yo Eight заявляет, что аннотация типа останется здесь обязательной. Я не уверен, что такое его рассуждение, но на самом деле совершенно легко написать свою собственную оболочку, которая предоставит любой правильно набранный кортеж с помощью метода bisequence
и не потребует аннотации типа:
import scalaz._, std.option._, std.tuple._
class BisequenceWrapper[F[_, _]: Bitraverse, G[_]: Applicative, A, B](
v: F[G[A], G[B]]
) {
def bisequence = implicitly[Bitraverse[F]].bisequence(v)
}
implicit def bisequenceWrap[F[_, _]: Bitraverse, G[_]: Applicative, A, B](
v: F[G[A], G[B]]
) = new BisequenceWrapper(v)
Теперь (some(1), some("a")).bisequence
будет компилироваться просто отлично.
Я не могу придумать, почему Scalaз не включил бы что-то вроде этого. Независимо от того, хотите ли вы добавить его в то же время, это вопрос вкуса, но, безусловно, нет теоретического препятствия, позволяющего компилятору печатать здесь.
Я понимаю, что вы спрашиваете о Scalaz, но стоит отметить, что стандартный метод не является невыносимо многословным:
val x = (Some(1), Some(2))
for (a <- x._1; b <-x._2) yield (a,b)
В общем случае (например, произвольные кортежи) Shapeless лучше всего подходит для такого рода вещей.
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> (Tuple2.apply[Int, Int] _).lift[Option].tupled
res5: (Option[Int], Option[Int]) => Option[(Int, Int)] = <function1>
scala> res5((some(3), some(11)))
res6: Option[(Int, Int)] = Some((3,11))
scala> res5((some(3), none))
res7: Option[(Int, Int)] = None