Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 约束函数的返回类型,该函数接受_Scala_Casting_Either - Fatal编程技术网

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
}