有
(Some(1), Some(2))
我希望得到
Some((1, 2))
并且
(Some(1), None)
我希望得到
None
答案 0 :(得分:31)
我意识到你在询问Scalaz,但值得指出的是标准方法并不是无法忍受的:
val x = (Some(1), Some(2))
for (a <- x._1; b <-x._2) yield (a,b)
在一般情况下(例如任意元组元组),Shapeless最适合这类事情。
答案 1 :(得分:15)
您可以使用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不会包含这样的东西。你是否想要在此期间添加它是一个品味问题,但是让编译器在这里进行打字绝对没有理论上的障碍。
答案 2 :(得分:4)
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
答案 3 :(得分:2)
从Scala 2.13
开始,Option#zip
在标准库中提供了这种确切的行为:
Some(2) zip Some('b') // Some((2, 'b'))
Some(2) zip None // None
None zip Some('b') // None
None zip None // None
在Scala 2.13
之前,Option#zip
返回一个Iterable
,可以将其与headOption
组合:
Some(2) zip Some('b') headOption // Some((2, 'b'))
Some(2) zip None headOption // None
答案 4 :(得分:1)
我认为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