简体   繁体   中英

Scala type bounds

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!"
}

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.

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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM