Type inference with existential type

♀尐吖头ヾ 提交于 2020-01-30 07:58:31

问题


I have a generic trait SomeTrait defined as so:

trait SomeTrait[T] {
  def foo(t: T): String
}

And methods bar and qux as so:

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 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. 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. 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.


回答1:


The correct way to do this is to use a type variable to give a name to 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.

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):

def fooOfBar[T](x: SomeTrait[T]) = x.foo(bar(x))
qux map { fooOfBar(_) }


来源:https://stackoverflow.com/questions/38627415/type-inference-with-existential-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!