转换选项的元组的元组与Scalaz或无形的选项(Converting a tuple of opti

2019-06-28 08:02发布

(Some(1), Some(2))

我期望能获得

Some((1, 2))

并具有

(Some(1), None)

我期望能获得

None

Answer 1:

您可以使用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目前这里所需要的类型注释。


在评论呦八个州,该类型的注释将在这里仍然是强制性的。 我不知道他或她的理由是什么,但它实际上是非常容易编写自己的包装,将提供任何适当类型的元组与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将不包括这样的事情。 无论你是否希望将其添加在此期间是一个品味的问题,但绝对没有理论上的障碍,在这里让编译器做打字。



Answer 2:

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

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

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

在一般情况下(如任意元数元组), 无形是最好的,在这样的事情。



Answer 3:

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


Answer 4:

我认为, 猫版本将不会在这里是多余的。

@ 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


Answer 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 


文章来源: Converting a tuple of options to an option of tuple with Scalaz or Shapeless