Rex*_*err 32

我意识到你在询问Scalaz,但值得指出的是标准方法并不是无法忍受的:

val x = (Some(1), Some(2))

for (a <- x._1; b <-x._2) yield (a,b)
Run Code Online (Sandbox Code Playgroud)

在一般情况下(例如任意元组元组),Shapeless在这种情况下是最好的.


Tra*_*own 16

您可以使用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))
Run Code Online (Sandbox Code Playgroud)

不幸的是,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)
Run Code Online (Sandbox Code Playgroud)

现在(some(1), some("a")).bisequence编译就好了.

我想不出一个很好的理由Scalaz不会包含这样的东西.你是否想在此期间添加它是一个品味问题,但是让编译器在这里进行输入绝对没有理论上的障碍.


Mik*_*kov 6

我认为cats版本在这里不会多余。

@ import cats.implicits._
import cats.implicits._

@ (4.some, 2.some).bisequence
res1: Option[(Int, Int)] = Some((4, 2))

@ (4.some, none).bisequence
res2: Option[Tuple2[Int, Nothing]] = None
Run Code Online (Sandbox Code Playgroud)


Xav*_*hot 5