Reputation: 11512
What is wrong with the code below? I'm getting the following complaint from the compiler on the indicated line: type arguments [Asset] do not conform to trait Worker's type parameter bounds [T <: br.Doable]
How is this so? Worker expects a subtype of Doable, and asset extends Doable.
trait Doable
trait Worker[T<:Doable] {
def hey():String
}
case class Asset() extends Doable
case class Hey[Asset] extends Worker[Asset] { // << error here
def hey() = "You!"
}
Upvotes: 2
Views: 792
Reputation: 3120
This has been asked a lot of times, and I think that the confusion can easily go away if you see the analogy between type parameters and constructor parameters, thinking about them just as different kinds of constructor parameters: type-level and value-level.
Disclaimer Of course, this is only an analogy and it will break at a lot of different levels and there are a lot of corner cases as with anything Scala; but my point here is that it can be useful
At the type level, you can think of <:
as a the equivalent of :
at the value level:
class TypeParamsVsVals {
type X
type X1 <: X
class Buh[T <: X]
class Oh[T1 <: X1] extends Buh[T1]
// wait for Scala 3
// class Oh[T1 <: X1] extends Buh[T = T1]
type x
type x1 <: x
class buh(val t: x)
class oh(val t1: x1) extends buh(t = t1)
}
What I think is the main source of confusion is that at the type level there's no kind distinction between the two sides of <:
, and to make things worse you can write T
without any (no pun intended) bound, while you cannot do the same at the value level:
class NoBounds[T]
// same as
class AltNoBounds[T <: Any]
// you cannot write
// class noBounds(val t)
class noBounds(val t: Any)
Upvotes: 0
Reputation: 30300
The problem is you have confused yourself by using the same value, Asset
, to refer to a case class and a type parameter.
You probably intend to do something like this:
case class Hey[T](str: String) extends Worker[Asset] {
def hey() = "You!"
}
Though it is beside the point, note that I added a parameter to Hey
because case classes without parameters have been deprecated.
Upvotes: 2
Reputation: 24802
When you declare case class Hey[Asset]
, you bind a new type variable Asset
, you do not refer to case class Asset() extends Doable
(you are shadowing the Asset
type variable).
Your code is equivalent to :
case class Hey[A] extends Worker[A] {
...
}
which obviously won't work.
Upvotes: 6