Dae*_*yth 9 polymorphism scala type-inference
我有一些像这样的代码:
sealed trait Foo[A] {
def value: A
}
case class StringFoo(value: String) extends Foo[String]
case class IntFoo(value: Int) extends Foo[Int]
Run Code Online (Sandbox Code Playgroud)
我想要一个可以使用A
给定子类型参数的类型的函数.
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何以dostuff
一种有效的方式声明.我能弄清楚的最接近的事情是
def dostuff[B <: Foo[A]](p: Param): A
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为A
在该位置未定义.我可以做点什么
def dostuff[A, B <: Foo[A]](p: Param): A
Run Code Online (Sandbox Code Playgroud)
但后来我必须调用它,就像dostuff[String, StringFoo](param)
它非常难看.
看起来编译器应该具有移动A
到返回类型所需的所有信息,如何在标准scala或库中进行此工作.如果这会影响答案,我现在在scala 2.10上.如果有可能的话,我会接受2.11的解决方案,但在2.10中是不可能的
另一种选择是使用类型成员:
sealed trait Foo {
type Value
def value: Value
}
case class StringFoo(value: String) extends Foo { type Value = String }
case class IntFoo(value: Int) extends Foo { type Value = Int }
def dostuff[B <: Foo](p: Any): B#Value = ???
// Hypothetical invocation
val i: Int = dostuff[IntFoo](param)
val s: String = dostuff[StringFoo](param)
Run Code Online (Sandbox Code Playgroud)
请注意,这两个解决方案主要解决Scala中的语法限制,您无法修复列表的一个类型参数并让编译器推断另一个.
您可能知道,如果您有一个类型的参数Foo[A]
,那么您可以使方法通用A
:
def dostuff[A](p: Foo[A]): A = ???
Run Code Online (Sandbox Code Playgroud)
因为这可能并非总是如此,我们可以尝试使用能表达之间的关系的隐含参数A
和B
.因为我们不仅可以将一些通用参数应用于方法调用(泛型参数推断是全部或全部),我们必须将其拆分为2个调用.这是一个选项:
case class Stuff[B <: Foo[_]]() {
def get[A](p: Param)(implicit ev: B => Foo[A]): A = ???
}
Run Code Online (Sandbox Code Playgroud)
您可以检查REPL中的类型:
:t Stuff[IntFoo].get(new Param) //Int
:t Stuff[StringFoo].get(new Param) //String
Run Code Online (Sandbox Code Playgroud)
沿着相同的行,但使用匿名类的另一个选项是:
def stuff[B <: Foo[_]] = new {
def apply[A](p: Param)(implicit ev: B <:< Foo[A]): A = ???
}
:t stuff[IntFoo](new Param) //Int
Run Code Online (Sandbox Code Playgroud)
在这里,我已经使用apply
了get
,所以你可以更自然地应用这个方法.另外,正如您的评论中所建议的那样,我<:<
在证据类型中使用过.对于那些希望了解有关此类广义类型约束的更多信息的人,可以在此处阅读更多内容.
您也可以考虑使用抽象类型成员而不是通用参数.在努力进行泛型类推理时,这通常会提供一种优雅的解决方案.您可以在此处阅读有关抽象类型成员及其与泛型的关系的更多信息.