I have the following simple demo code, which give me the type mismatch error. I quite do not understand why this error happens. Would anyone show me how to fix this error. Further explain or related learning resource would be great thankful.
object Application extends App {
private val foo = new Foo
private val holder = new FooTypeHolder
private val client = new Client(holder)
client.showElementType(foo)
}
class Foo
trait TypeHolder[T] {
type ElementType = T
}
class FooTypeHolder extends TypeHolder[Foo]
class Client[T <: TypeHolder[_]](val holder: T) {
def showElementType(t: T#ElementType): Unit = {
println("show element type " + t.toString)
println(t.getClass)
}
}
The compile error as:
Error:(10, 26) type mismatch;
found : Application.foo.type (with underlying type Foo)
required: _$1
client.showElementType(foo)
UPDATE at 2018-03-15
Just like Andrey Tyukin would be curious about what TypeHolder
is used for, it contains nothing beyond T
. I add some function on this trait.
Codes as follow.
object Application extends App {
private val foo = new Foo
private val holder = new FooTypeHolder
private val client = new Client(holder)
client.showElementType(foo)
}
class Foo
trait TypeHolder[T] {
type ElementType = T
def holderFun(): Unit = println(s"holder, type:${getClass}")
def elementFun(ele: ElementType): Unit = println(s"element, type:${getClass}")
}
class FooTypeHolder extends TypeHolder[Foo]
class Client[T <: TypeHolder[_]](val holder: T) {
def showElementType(t: T#ElementType): Unit = {
println("show element type " + t.toString)
holder.holderFun()
holder.elementFun(t)
}
}
which gives compile errors as below:
Error:(10, 26) type mismatch;
found : o2.Application.foo.type (with underlying type o2.Foo)
required: _$1
client.showElementType(foo)
Error:(30, 23) type mismatch;
found : _$1
required: Client.this.holder.ElementType
(which expands to) _$1
holder.elementFun(t)
On the whole, The core thing I want to know is:
when I instantiate client
via val client = new Client(holder)
while holder
has the type: TypeHolder[Foo]
Does scala compiler can infer the ElementType
of hoder
is "Foo
"?
Thanks so much @Andrey for giving various workable solutions. I exam your code snippet 1~3, and compare with my code carefully, which makes me more clear now. However I still have some questions.
Version 3
This version of your code is closest to my original post code. The only difference is the type restriction of function showElementType
- Mine:
def showElementType(t: T#ElementType): Unit
- Your:
def showElementType(t: holder.ElementType): Unit
Which confuse me is, since "(t: holder.ElementType)
" works, "(t: T#ElementType)
" should work as well? And actually it isn't. why?
Version 2
The difference here is the location of type ElementType = T
. I put it in the trait definition, while you put it in type parameter restriction.
- Mine:
trait TypeHolder[T] { type ElementType = T}
- Your:
class Client[T, H <: TypeHolder { type ElementType = T }]
I cannot understand why the assignment statement in trait definition isn't works.
Version 1
You use two type parameter T
& H
to capture the type of Foo
and TypeHolder
respectively. It should absolutely works. The type of client is also corresponding to Client[Foo, TypeHolder[Foo]]
. My question is, is it possible to define client use only one type parameter, e.g. Client[TypeHolder[Foo]]
. In other words, is it possible for the compiler to infer from the TypeHolder[Foo]
that the ElementType
is Foo
?
Thank you.