I have the following piece of code
trait HTMLWritable {
def toHTML: String
}
case class User(name: String, age: Int, email: String) extends HTMLWritable {
override def toHTML: String = s"<div> $name ($age) <a href=$email/> </div>"
}
trait HTMLSerializer[T] {
def serialize(value: T): String
}
implicit object UserSerializer extends HTMLSerializer[User] {
override def serialize(user: User): String = s"<div> ${user.name} (${user.age}) <a href=${user.email}/> </div>"
}
implicit class HTMLEnrichment[T](value: T) {
def toHTML(serializer: HTMLSerializer[T]): String = serializer.serialize(value)
}
val john = User("John", 32, "[email protected]")
println(john.toHTML(UserSerializer))
which produces the following error
Error:(30, 23) type mismatch;
found : advanced.StackOverflowQuestion.UserSerializer.type
required: Int
println(john.toHTML(UserSerializer))
the error will disappear if I rename HTMLWritable
's toHTML
method to toHtml
or in general to something else and keeping the print statement intanct like so
trait HTMLWritable {
def tohtml: String
}
case class User(name: String, age: Int, email: String) extends HTMLWritable {
override def tohtml: String = s"<div> $name ($age) <a href=$email/> </div>"
}
and the question: Why is the compiler confused here?
I would expect that the class method would be preferred and only defer to the implicit if the method was not found but this type mismatch is a completely different beast.
Compiler thinks that .toHTML
in john.toHTML(UserSerializer)
is method HTMLWritable#toHTML
instead of extension method HTMLEnrichment#toHTML
.
Then according to HTMLWritable#toHTML
signature, john.toHTML
is a String
and john.toHTML(UserSerializer)
is john.toHTML.apply(UserSerializer)
i.e. String#apply
expecting Int
.