如何将Either初始化为Right并指定Left的类型?

How to initialize an Either to Right and specify the type of Left?

我想将 Either 初始化为 Left,但这需要指定 Right 面的类型(反之亦然)。

如果我不这样做,则 Right 端默认输入 Nothing,以便执行以下操作:

List(5, 42, 7).foldLeft(Left("empty")) {
  case (Left(_), i)  => Right(i)
  case (Right(s), i) => Right(s + i)
}
error: type mismatch;
    found   : scala.util.Right[Nothing,Int]
    required: scala.util.Left[String,Nothing]

我显然被迫详细提供 Either 两边的类型:

List(5, 42, 7).foldLeft(Left("empty"): Either[String, Int]) {
  case (Left(_), i)  => Right(i)
  case (Right(s), i) => Right(s + i)
}

以类似的方式,我可以使用Option.empty[Int]None初始化为Option[Int],有没有办法将Left("smthg")初始化为[=22] =]?

启动 Scala 2.13Left 带有一个 Left#withRight 方法,允许将 Left[A, Nothing] 向上转换为 Either[A, B]:

Left("smthg").withRight[Int]
// Either[String, Int] = Left("smthg")
Left("smthg")
// Left[String, Nothing] = Left("smthg")

Right 方面和 withLeft:

也是如此
Right(42).withLeft[String]
// Either[String, Int] = Right(42)

在你的情况下给出:

List(5, 42, 7).foldLeft(Left("empty").withRight[Int]) {
  case (Left(_),  i) => Right(i)
  case (Right(s), i) => Right(s + i)
}
// Either[String, Int] = Right(54)

为了补充 Xavier 的答案,cats 还提供了用于创建 Either 的实用方法,例如,我们可以这样做:

import cats.implicits._

val right = 7.asRight[String] // Either[String, Int]

val left: = "hello cats".asLeft[Int] // Either[String, Int]

如果我们的项目使用 scala 2.12 或更低版本,它可能会有用。

如果我们不需要整个 cats 库,我们当然可以只借 extension functions for either:

implicit class EitherIdOps[A](private val obj: A) extends AnyVal {

  /** Wrap a value in `Left`. */
  def asLeft[B]: Either[A, B] = Left(obj)

  /** Wrap a value in `Right`. */
  def asRight[B]: Either[B, A] = Right(obj)

}