简体   繁体   中英

Scala type inference when mixing type member and type parameter

I have the following definitions:

trait Xode[+R] {
  type S = Option[R]
}
case class AXode(a: Int) extends Xode[Int]
case class BXode(b: String) extends Xode[String]

object xtore {
  private var m: Map[Xode[_], Xode[_]#S] = Map()

  def put[A <: Xode[_]](k: A)(v: A#S) {
    m += k -> v    
  }  
}

When executing the following, no error is raised, although I expect AXode#S to be Option[Int].

xtore.put(AXode(5))(Some("apples")) // <-- no error

What might happen is that A is inferred to be Xode[_] , and then Xode[_]#S gets to be Option[_] . Could I express my intention with type parameters?

When implemented with R being an abstract type member instead of a type parameter, it works as expected. Or dependent method types and typing v: kS also helps. Is there any other construct?

Some (maybe slightly wrong explanation)

X[_] means X[Any] . In particular your map does not relate the value types to the key types over the wild-carded argument to the Xode type constructor. In addition in put , scalac can widen the type of A to Xode[Any] if it needs to. Disclaimer: I'm not 100% sure about what I'm writing

Code that passes the question

The following rejects xtore.put(AXode(5))(Some("apples")) and accepts xtore.put(AXode(5))(Some(0)) . Note that you also need to capture the type parameter of Xode as opposed to the Xode[_] version in the OP. I don't understand it completely and there might be a simpler solution.

  def put[A,B[X] <: Xode[X]](k: B[A])(v: B[A]#S) {
    m += k -> v    
  }

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