scala - 如何引用更高种类的类型参数的参数?

标签 scala generics

假设你有这样的特质:

trait Foo[A]{
    def foo: A
}

我想创建一个这样的函数:

def getFoo[A <: Foo[_]](a: A) = a.foo

Scala 编译器推导出 Any对于这个函数的返回类型。
如何引用匿名参数_getFoo 的签名(或正文)中?
换句话说,我怎样才能取消匿名参数?

我希望能够使用类似的功能

object ConcreteFoo extends Foo[String] {
  override def foo: String = "hello"
}

val x : String = getFoo(ConcreteFoo)

由于明显的原因导致编译失败,因为 getFoo隐式声明为 Any .

如果 Scala (2.12)无法做到这一点,我会对这种限制的理性或技术原因感兴趣。
我确信有关于此的文章和现有问题,但我似乎缺少正确的搜索词。

更新:现有答案准确地回答了我所说的问题,但我想我对我的实际用例不够准确。对困惑感到抱歉。我希望能够写作

def getFoo[A <: Foo[_]] = (a: A) => a.foo

val f = getFoo[ConcreteFoo.type]

//In some other, unrelated place
val x = f(ConcreteFoo)

因为我没有 A 类型的参数,编译器无法推导出参数RA如果我做

def getFoo[R, A <: Foo[R]]: (A => R) = (a: A) => a.foo

喜欢建议。我想避免手动提供类型参数 R (在这种情况下为 String),因为它感觉是多余的。

最佳答案

从字面上回答您的确切问题:

def getFoo[R, A <: Foo[R]](a: A): R = a.foo

但是由于您不使用类型 A , 你实际上可以省略它和 <: Foo[..]完全绑定(bind),只保留返回类型:
def getFoo[R](a: Foo[R]): R = a.foo

更新 (问题已经发生了相当大的变化)

你可以偷运一个额外的apply从单独的隐式返回类型见证推断返回类型的调用:
trait Foo[A] { def foo: A }

/** This is the thing that remembers the actual return type of `foo`
  * for a given `A <: Foo[R]`.
  */
trait RetWitness[A, R] extends (A => R)

/** This is just syntactic sugar to hide an additional `apply[R]()`
  * invocation that infers the actual return type `R`, so you don't
  * have to type it in manually.
  */
class RetWitnessConstructor[A] {
  def apply[R]()(implicit w: RetWitness[A, R]): A => R = w
}

def getFoo[A <: Foo[_]] = new RetWitnessConstructor[A]

现在它看起来几乎就像你想要的,但你必须提供隐含的,你必须调用 getFoo[ConcreteFoo.type]()加上一对圆括号:
object ConcreteFoo extends Foo[String] {
  override def foo: String = "hey"
}

implicit val cfrw = new RetWitness[ConcreteFoo.type, String] {
  def apply(c: ConcreteFoo.type): String = c.foo
}

val f = getFoo[ConcreteFoo.type]()
val x: String = f(ConcreteFoo)

我不确定它是否真的值得,这不一定是最直接的事情。隐含的类型级计算,隐藏在一些微妙的语法糖后面:这可能是隐藏在这两个括号后面的太多魔法() .除非您期望返回类型为 foo会经常更改,将第二个通用参数添加到 getFoo 可能更容易,并显式写出返回类型。

关于scala - 如何引用更高种类的类型参数的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55828235/

相关文章:

c# - 可以从 C# 类型转换为 System.Type,但反之则不行

java - Collections.max 签名的解释

scala - Prod 在 shapeless 中的 Int 值

scala - SSLException :Unrecognized SSL message, 明文连接

java - 不能在 Java 中使用 Scala 类

c# - 使用 Vector2 和 Vector2 作为通用约束?

Java - 从接受泛型的类继承?

java - 如何为返回实现类型的抽象类编写方法?

scala - 什么会导致阶段在 Spark 中重新尝试

scala - 值 unsafePerformSync 不是 scalaz.concurrent.Task[String] 的成员