假设我需要在Scala中转换Option[Int]
为Either[String, Int]
.我想这样做:
def foo(ox: Option[Int]): Either[String, Int] = ox.fold(Left("No number")) {x => Right(x)}
不幸的是上面的代码没有编译,我需要Either[String, Int]
显式添加类型:
ox.fold(Left("No number"): Either[String, Int]) { x => Right(x) }
是否可以在不添加类型的情况下转换Option
为Either
这种方式?
您如何建议转换Option
为Either
?
不,如果你这样做,你不能忽略这种类型.
Left("No number")
推断的类型是Either[String, Nothing]
.从刚才Left("No number")
的编译器无法知道你想要的第二种类型的Either
是Int
,和类型推断并不到目前为止,编译器将着眼于整个方法,并决定它应该去Either[String, Int]
.
您可以通过多种不同方式完成此操作.例如,使用模式匹配:
def foo(ox: Option[Int]): Either[String, Int] = ox match { case Some(x) => Right(x) case None => Left("No number") }
或者用if
表达式:
def foo(ox: Option[Int]): Either[String, Int] = if (ox.isDefined) Right(ox.get) else Left("No number")
或者Either.cond
:
def foo(ox: Option[Int]): Either[String, Int] = Either.cond(ox.isDefined, ox.get, "No number")
我不确定您当时使用的是哪个版本的Scala.目前,使用Scala 2.12.6,您的代码没有编译问题,如下所示:
def foo(ox: Option[Int]): Either[String, Int] = ox.toRight("No number")
我想提出的另一点是折叠(虽然它是我首选折叠任何有折叠方法的方法),但通常需要有关类型参数的帮助.编译器可以通过两种方式检查表达式,它可以推断出类型参数,也可以简单地找到明确定义的参数.
在您的示例中,如果您尝试折叠选项,请执行以下操作:
def foo(ox: Option[Int]): Either[String, Int] = ox.fold(Left("No number") : Either[String, Int])(x => Right(x))
您明确提供有关第一个参数的类型信息,然后可以使用它来推断类型参数fold
.你正在帮助类型推断机制.
另一方面,您可以简单地显式提供类型参数,fold
如下所示:
def foo(ox: Option[Int]): Either[String, Int] = ox.fold[Either[String, Int]](Left("No number"))(x => Right(x))
现在你的实际(值级)参数没有多余的类型信息,并且当编译器查看它时没有类型推断,它可以立即告诉什么fold
类型参数,因为它已经明确提供.使用方括号显式指定类型参数.
还有一点,关于x => Right(x)
这里你实际上是在创建一个新的函数文字,除了将x传递apply
给Right case类的伴随对象的方法之外什么都不做.您已经拥有适当形状的功能.它需要x
并返回一个Right(x)
.这是apply
方法.你可以直接引用它(传递它).
def foo(ox: Option[Int]): Either[String, Int] = ox.fold[Either[String, Int]](Left("No number"))(Right.apply)