鉴于以下内容:
trait A[X] {
def foo(): X
}
class B[T <: A[_]] {
def getFoo(a:T) = a.foo()
}
class C[T <: A[Z], Z] {
def getFoo(a:T):Z = a.foo()
}
是否有可能使B像C一样工作?具体来说是获取a.foo()的结果类型。
scala> var b:B[A[Int]] = new B[A[Int]]()
scala> b.getFoo(AA(1))
res0: Any = 1
scala> var c:C[A[Int],Int] = new C[A[Int],Int]()
c: C[A[Int],Int] = C@4cc36c19
scala> c.getFoo(AA(1))
res1: Int = 1
b返回Any,但c正确返回Int。这显然是一个人为的例子,但如果我可以从Generic类型中提取子类型,它将通过代码大大简化。基本上,了解&#34; Z&#34; (在C中使用),而不必明确地传递它 - 从A的类型推断。
显然,C可以根据需要运行,但问题是我的框架更类似于:
class D[T <: A[Z1], U <: B[Z2], Z1, Z2] extends E[T,U,Z1,Z2]
然后要求框架的用户使用4个类型参数实现,理想情况下它只是2
class D[T <: A[_], U <: B[_]] extends E[T,U]
不是阻止程序,只是尝试简化公开的API。
答案 0 :(得分:2)
您可以执行以下某些基于类型类的库中经常使用的内容:
trait Foo[H[_] <: Langh[_]]{
def thing[A](ha: H[A]): A = ha.ha()
}
这会将type参数的解析推送到方法thing
的调用。它使用更高级的类型。
事实上,如果你看一下像ScalaZ这样的库,你会看到这种模式:
trait Functor[F[_]]{
def map[A, B](fa: F[A])(f: A => B): F[B]
}
回复评论
无法使用U <: T[_]
类型,然后能够提取实际T[A]
的类型参数,因为它的定义会丢失该信息。如果以上内容对您不起作用,那么我建议输入类:
trait Foo[U]{
def doStuff(u: U)(implicit ev: MyTypeClass[U]): ev.A = //...
}
其中您只定义MyTypeClass
隐含,如下所示:
trait Whatever[FA]{ /*...*/ }
object Whatever{
implicit def WhateverMTC[F[_] <: Bound[_], A0] = new MyTypeClass[F[A0]]{
type A = A0
//...
}
}
然后你可以将你的类型绑定在隐式上,你的隐式携带约束,你的类型必须更高 - 并且你可以得到一个方法,在调用站点声明返回内部“隐藏”类型。 / p>
也就是说,当第一个建议更优雅,更清晰地处理问题时,这是很多机器。