繁体   English   中英

如何参考更高阶型参数的参数?

[英]How to reference parameter of a higher kinded type parameteter?

假设你有这样的特征:

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[..]完全绑定,只保留返回类型:

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]

现在它看起来几乎就像你想要的那样,但是你必须提供隐含的,你必须用另外一对圆形的parens来调用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)

我不确定它是否真的值得,它不一定是最直接的事情。 带有隐含的类型级计算,隐藏在一些微妙的语法糖背后:这可能是隐藏在这两个parens ()后面的太多魔法。 除非您期望foo的返回类型会经常更改,否则可能更容易向getFoo添加第二个泛型参数,并明确地写出返回类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM