2
votes

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?

1
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 ;)ziggystar
Yes, I'm less concerned about the Map (its type can't express what I want, that's why I hide it), but would like put to behave correctly.ron

1 Answers

1
votes

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    
  }