As a prelude, please don’t post screenshots like this. Copy and paste into a ```-delimited block, like I’m about to do. (It would indeed be kind of you to edit your post this way now, so that those who cannot read your screenshot can tell what you’re asking.)
For your second question, you’ve done a fine job breaking it down, but it can go even further towards its essence. The difference is exactly that between Buf
and ImSeq
in the following test.
trait Imagine {
type Top
type IfLeft <: Top
type IfRight <: Top
type Buf[A]
type ImSeq[+A]
def Buf[A]: Buf[A]
def ImSeq[A]: ImSeq[A]
def bufTrial = if (true) Buf[IfLeft] else Buf[IfRight]
def seqTrial = if (true) ImSeq[IfLeft] else ImSeq[IfRight]
}
scala> def trialTypes(i: Imagine) = (i.bufTrial, i.seqTrial)
trialTypes: (i: Imagine)(i.Buf[_1], i.ImSeq[i.Top])
forSome { type _1 >: i.IfLeft with i.IfRight <: i.Top }
To digress to your first question: in your example, the type argument to Buffer
takes the form E >: LB <: UB
. (In my Buf
case, too.) In your example, E is elided, whereas it’s the explicitly bound _1
in my example; the difference is of no consequence in this example.
The LB you see (make sure to read all the way to the <:
!) is the intersection or greatest lower-bound of the two possible values for the type parameter; this is much more obvious in my example.
The UB you see is the least upper-bound (in a sense, “union”) of the two possible values for the type parameter. In my example, the abstract type Top
is the best choice, so that is what is chosen.
Returning to your second question: the declaration of my ImSeq
, as well as Seq
and List
, implies that for all T, ImSeq[_ <: T] = ImSeq[T]
. The latter form is simpler, i.e. just showing the UB, and more probably what you want (it is in this case, right?), so Scala inference just picks that.
On the other hand, this is not and cannot be true for Buffer
. So you get the full form written out.
Sorry, subtyping is kind of complicated.
In Scalaz, we avoid this sort of thing by providing some
and none
functions that return the desired Option[T]
types rather than subtypes thereof. You can use these simple utility functions, or explicit : Ascription
to get the type you desire.