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: k.S also helps. Is there any other construct?
Some (maybe slightly wrong explanation)
X[_]meansX[Any]. In particular your map does not relate the value types to the key types over the wild-carded argument to theXodetype constructor. In addition input, scalac can widen the type ofAtoXode[Any]if it needs to. Disclaimer: I’m not 100% sure about what I’m writingCode that passes the question
The following rejects
xtore.put(AXode(5))(Some("apples"))and acceptsxtore.put(AXode(5))(Some(0)). Note that you also need to capture the type parameter ofXodeas opposed to theXode[_]version in the OP. I don’t understand it completely and there might be a simpler solution.