19

(Some(1), Some(2))

我希望得到

Some((1, 2))

并拥有

(Some(1), None)

我希望得到

None
4

5 回答 5

33

我知道你在问 Scalaz,但值得指出的是,标准方法并不是令人难以忍受的罗嗦:

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

for (a <- x._1; b <-x._2) yield (a,b)

在一般情况下(例如任意元组),Shapeless最擅长这种事情。

于 2012-09-13T14:15:23.360 回答
16

您可以使用 Scalaz 7Bitraverse为元组提供一个实例,然后像往常一样进行排序(但使用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 不包括这样的东西。在此期间是否要添加它是个人喜好问题,但让编译器在这里进行输入绝对没有理论上的障碍。

于 2012-09-13T15:02:57.930 回答
8

我认为cat版本在这里不会是多余的。

@ 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
于 2018-10-17T20:34:27.643 回答
5
  • 开始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.13Option#zip正在返回一个Iterable并且可以将它与headOption

    Some(2) zip Some('b') headOption // Some((2, 'b'))
    Some(2) zip None headOption      // None
    
于 2019-02-08T22:08:04.530 回答
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
于 2012-09-13T14:56:25.647 回答