[英]Type inference with existential type
I have a generic trait SomeTrait
defined as so: 我有一个通用特征SomeTrait
定义为:
trait SomeTrait[T] {
def foo(t: T): String
}
And methods bar
and qux
as so: 和方法bar
和qux
一样:
def bar[T](t: SomeTrait[T]): T
def qux: List[SomeTrait[_]]
I do not have control over the above. 我无法控制以上内容。 I am trying to operate on the list returned by qux
, like so 我正在尝试对qux
返回的列表进行操作,就像这样
qux map { x => x.foo(bar(x))}
However, the compiler complains that the types don't match up. 但是,编译器抱怨类型不匹配。 As far as I know this should be fine. 据我所知,这应该没问题。
I have tried adding a generic method (signature [T](SomeTrait[T])String
), and calling that to do the work, but the compiler still complains. 我尝试添加一个通用方法(签名[T](SomeTrait[T])String
),然后调用它来完成工作,但是编译器仍然抱怨。 I can cast my way around it like this: 我可以这样处理:
qux map { x =>
val casted = x.asInstanceOf[SomeTrait[T forSome { type T }]] // !!!
casted.foo(bar(casted))
}
But this is even more perplexing, as x
already has the type SomeTrait[_]
and SomeTrait[T forSome { type T }]
means the same thing. 但这更加令人困惑,因为x
已经具有SomeTrait[_]
类型和SomeTrait[T forSome { type T }]
意味着同一件事。 The only difference that I'm aware of is that the former is a shorthand for the latter that makes the compiler create its own synthetic names. 我知道的唯一区别是,前者是后者的简写,后者使编译器创建自己的综合名称。 I'm hoping there's a better way to do this. 我希望有更好的方法可以做到这一点。 I have seen this question however I don't think it applies. 我已经看到了这个问题,但是我认为它不适用。
The correct way to do this is to use a type variable to give a name to T
: 正确的方法是使用类型变量为T
命名:
qux map { case x: SomeTrait[t] => x.foo(bar(x)) }
This way the compiler knows bar(x): t
and so it's an acceptable argument to x.foo
. 这样,编译器就知道bar(x): t
,因此它是x.foo
的可接受参数。
Or, alternately, you can combine foo
and bar
into one method (remember that methods can be local, so you can just define it where you need it): 或者,也可以将foo
和bar
组合为一个方法(请记住,方法可以是局部的,因此您可以在需要的地方定义它):
def fooOfBar[T](x: SomeTrait[T]) = x.foo(bar(x))
qux map { fooOfBar(_) }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.