Scala 约束函数的返回类型,该函数接受
我正试着做一个这样的函数:Scala 约束函数的返回类型,该函数接受,scala,casting,either,Scala,Casting,Either,我正试着做一个这样的函数: def foo(x: Either[String, Int]) = x match { case Left(s) => Left("foo:" + s) case Right(n) => Right(n+1) } 这是可行的,但我正在寻找一种方法来向调用者保证,结果将始终与输入的类型相同——如果输入为左,则返回左,如果输入为右,则返回右 有人能想出一个巧妙的方法让我这么做吗 我知道,我能做到: def foo[T <: Eithe
def foo(x: Either[String, Int]) = x match {
case Left(s) => Left("foo:" + s)
case Right(n) => Right(n+1)
}
这是可行的,但我正在寻找一种方法来向调用者保证,结果将始终与输入的类型相同——如果输入为左,则返回左,如果输入为右,则返回右
有人能想出一个巧妙的方法让我这么做吗
我知道,我能做到:
def foo[T <: Either[String, Int]](x: T): T = (x match {
case Left(s) => Left("foo:" + s)
case Right(n) => Right(n+1)
}).asInstanceOf[T]
def foo[T左(“foo:+s”)
案例右侧(n)=>右侧(n+1)
}).ASINSTANCOF[T]
……但最后的演员阵容是丑陋的:(
这个声明将是一个基本特性的抽象成员,几个实现“插件”将需要覆盖它,我不想让所有的插件都必须进行这种类型转换
我还可以创建两个单独的函数fooString
,和fooInt
…但由于一些考虑因素,这是我想要避免的,具体到我正在使用的特定api
还有其他想法吗?如果您不局限于使用其中任何一种,您可以使用类型类-
sealed trait Transformer[A] {
def transform(n: A): A
}
object Transformer {
implicit object IntTransformer extends Transformer[Int] { def transform(n: Int) = n + 1 }
implicit object StringTransformer extends Transformer[String] { def transform(s: String) = "foo:" + s }
}
def foo[A: Transformer](x: A)(implicit transformer: Transformer[A]) = transformer.transform(x)
这个签名实际上并没有说你想要它说什么:
val x = Left("a")
val y = foo[x.type](x)
y
的类型是x.type
,因此它必须是相同的实例,而不是相同的实例。因此,如果要避免强制转换,您需要更改签名。一种方法(未测试):
trait LowPriorityFooImplicits{{{uU3:FooImplicits=>
隐式def eitherFoo(x:other[String,Int]):Foo[other[String,Int]]=newfoo(x){
def foo()=x匹配{
案例y:Left[String,Int]=>y.foo()
案例z:Right[String,Int]=>z.foo()
}
}
trait fooinflicits扩展了lowpriorityfooinflicits{
sealed trait Foo[A如果您确实想专门处理other
,您还可以创建隐式Transformer[Left/Right/other[String,Int]]
(other
将按类型匹配模式)。
trait LowPriorityFooImplicits { _: FooImplicits =>
implicit def eitherFoo(x: Either[String, Int]): Foo[Either[String, Int]] = new Foo(x) {
def foo() = x match {
case y: Left[String, Int] => y.foo()
case z: Right[String, Int] => z.foo()
}
}
trait FooImplicits extends LowPriorityFooImplicits {
sealed trait Foo[A <: Either[String, Int]](x: A) {
def foo(): A
}
implicit def leftFoo(x: Left[String, Int]): Foo[Left[String, Int]] = new Foo(x) {
def foo() = Left(fooString(x.value))
}
implicit def rightFoo ...
// x will be implicitly converted from a subtype of Either[String, Int]
def foo[A](x: Foo[A]): T = x.foo()
protected def fooString(s: String) = "foo:" + s
protected def fooInt(n: Int) = n + 1
}