简体   繁体   中英

Mapping over a list of existential types

I have a list of existientially-typed objects I want to map over. Something like this:

sealed abstract class IntBox(val v: Int)
case object IB1 extends IntBox(1)
case object IB2 extends IntBox(2)

case class Adder[A  <: IntBox](ib: A, v: Int) {
  def add(i: A) = v + i.v
}

val adders: List[Adder[_ <: IntBox]] = List(Adder(IB1, 0), Adder(IB2, 0))

adders.map(adder => adder.add(adder.ib))

However, I'm getting an error like

found: adder.ib.type
required: _$1

I feel it's something like because the map somehow unifies the different IntBox s into one unobtainable anonymous type...

Can I get what I want without casting (ie adder.asInstanceOf[Adder[adder.ib.type]]... ?

The type is not unobtainable, you can get it using type pattern matching:

adders.map{ case a: Adder[t] => a.add(a.ib) }

Here, the existential type parameter is bound to type variable t , and the compiler can correctly infer additional properties of t that it cannot infer for the whole list.

Refer to section 8.3.1 of the Specification for more details.


Full code with trait replaced by class to make it compile

sealed abstract class IntBox(val v: Int)
case object IB1 extends IntBox(1)
case object IB2 extends IntBox(2)

case class Adder[A  <: IntBox](ib: A, v: Int) {
  def add(i: A) = v + i.v
}

val adders: List[Adder[_ <: IntBox]] = List(Adder(IB1, 0), Adder(IB2, 0))

adders.map{ case a: Adder[t] => a.add(a.ib) }

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