在 Scala 中将选项转换为任一
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34706443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert Option to Either in Scala
提问by Michael
Suppose I need to convert Option[Int]to Either[String, Int]in Scala. I'd like to do it like this:
假设我需要在 Scala 中转换Option[Int]为Either[String, Int]。我想这样做:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number")) {x => Right(x)}
Unfortunately the code above doesn't compile and I need to add type Either[String, Int]explicitly:
不幸的是,上面的代码无法编译,我需要Either[String, Int]显式添加类型:
ox.fold(Left("No number"): Either[String, Int]) { x => Right(x) }
Is it possible to convert Optionto Eitherthis way without adding the type ?
How would you suggest convert Optionto Either?
是否可以在不添加类型的情况下转换Option为Either这种方式?
您建议如何转换Option为Either?
回答by Jesper
No, if you do it this way, you can't leave out the type.
不,如果你这样做,你不能遗漏类型。
The type of Left("No number")is inferred to be Either[String, Nothing]. From just Left("No number")the compiler can't know that you want the second type of the Eitherto be Int, and type inference doesn't go so far that the compiler will look at the whole method and decide it should be Either[String, Int].
的类型Left("No number")推断为Either[String, Nothing]。仅从Left("No number")编译器无法知道您想要的第二种类型Either是Int,并且类型推断不会走得太远以至于编译器会查看整个方法并决定它应该是Either[String, Int]。
You could do this in a number of different ways. For example with pattern matching:
您可以通过多种不同的方式来做到这一点。例如模式匹配:
def foo(ox: Option[Int]): Either[String, Int] = ox match {
case Some(x) => Right(x)
case None => Left("No number")
}
Or with an ifexpression:
或者用一个if表达式:
def foo(ox: Option[Int]): Either[String, Int] =
if (ox.isDefined) Right(ox.get) else Left("No number")
Or with Either.cond:
或与Either.cond:
def foo(ox: Option[Int]): Either[String, Int] =
Either.cond(ox.isDefined, ox.get, "No number")
回答by Peter Perhá?
I am not sure which version of Scala you were using at the time. Currently, with Scala 2.12.6 there's no compilation problems with your code like this:
我不确定您当时使用的是哪个版本的 Scala。目前,使用 Scala 2.12.6,您的代码没有像这样的编译问题:
def foo(ox: Option[Int]): Either[String, Int] =
ox.toRight("No number")
One other point I'd like to make is that folding (while it's my preferred method of collapsing just about anything that has a fold method on it) quite often requires help with type parameters. There's two ways the compiler can type check an expression, either it can infer the type parameters or it can simply find them explicitly defined.
我想提出的另一点是折叠(虽然这是我折叠几乎任何具有 fold 方法的东西的首选方法)经常需要类型参数的帮助。编译器可以通过两种方式对表达式进行类型检查,或者可以推断类型参数,或者可以简单地找到明确定义的类型。
In your example, if you're trying to fold an option like so:
在您的示例中,如果您尝试折叠这样的选项:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number") : Either[String, Int])(x => Right(x))
You're explicitly providing type information about the first argument, which in turn can be then used to infer the type parameter of fold. You're aiding the type inference mechanism.
您明确提供有关第一个参数的类型信息,然后可以使用它来推断 的类型参数fold。您正在帮助类型推断机制。
On the other hand, you could simply just explicitly provide the type parameter for foldlike so:
另一方面,您可以简单地显式提供类型参数,fold如下所示:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(x => Right(x))
Now your actual (value-level) arguments are not littered with superfluous type information, and there's no type inference going on when the compiler looks at it, it can tell right away what fold's type parameter is, as it's been explicitly provided. Use the square brackets to specify the type parameter explicitly.
现在,您的实际(值级)参数不再充斥着多余的类型信息,并且在编译器查看它时不会进行类型推断,它可以立即知道fold的类型参数是什么,因为它已被明确提供。使用方括号明确指定类型参数。
One more point, regarding x => Right(x)here you're practically creating a new function literal that does nothing other than pass x into the applymethod of the Right case class's companion object. You already have a function of the appropriate shape available. It takes xand returns a Right(x). It is the applymethod. You can refer to it (pass it) directly.
还有一点,关于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)

