您可以使用 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 可以正常编译了。
我想不出 Scalaz 不包含此类内容的充分理由。在此期间是否要添加它是个人喜好问题,但让编译器在这里进行输入绝对没有理论上的障碍。