Scala: Typecast sem parâmetro de tipo explicitamente conhecido

Considere o seguinte exemplo:

case class C[T](x:T) {
  def f(t:T) = println(t)
  type ValueType = T
}

val list = List(1 -> C(2), "hello" -> C("goodbye"))

for ((a,b) <- list) {
  b.f(a)
}

Neste exemplo, eu sei (garantia de tempo de execução) que o tipo dea será algumTeb terá tipoC[T] com o mesmoT. Obviamente, o compilador não pode saber disso, portanto, obtemos um erro de digitação emb.f(a).

Para dizer ao compilador que esta chamada está correta, precisamos fazer uma conversão de tipo àb.f(a.asInstanceOf[T]). Infelizmente,T não é conhecido aqui. Então, minha pergunta é: como reescreverb.f(a) para fazer esse código compilar?

Estou procurando uma solução que não envolva construções complexas (para manter o código legível) e que seja "limpa" no sentido de que não devemos confiar na eliminação do código para fazê-lo funcionar (consulte a primeira abordagem abaixo).

Tenho algumas abordagens de trabalho, mas as acho insatisfatórias por várias razões.

Abordagens que tentei:
b.asInstanceOf[C[Any]].f(a)

Isso funciona e é razoavelmente legível, mas é baseado em uma "mentira".b não é do tipoC[Any], e a única razão pela qual não obtemos um erro de tempo de execução é porque dependemos das limitações da JVM (apagamento de tipo). Eu acho que é bom estilo só usarx.asInstanceOf[X] quando sabemos quex é realmente do tipoX.

  b.f(a.asInstanceOf[b.ValueType])

Isso deve funcionar de acordo com meu entendimento do sistema de tipos. Eu adicionei o membroValueType para a aulaC para poder se referir explicitamente ao parâmetro typeT. No entanto, nessa abordagem, recebemos uma mensagem de erro misteriosa:

Error:(9, 22) type mismatch;
 found   : b.ValueType
    (which expands to)  _1
 required: _1
  b.f(a.asInstanceOf[b.ValueType])
                    ^

Por quê? Parece reclamar que esperamos tipo_1 mas tem tipo_1! (Mas, mesmo que essa abordagem funcione, ela se limita aos casos em que temos a possibilidade de adicionar um membroValueType paraC. E seC é alguma classe de biblioteca existente, também não podemos fazer isso.)

for ((a,b) <- list.asInstanceOf[List[(T,C[T]) forSome {type T}]]) {
  b.f(a)
}

Este funciona e é semanticamente correto (ou seja, não "mentimos" ao invocarasInstanceOf) A limitação é que isso é um tanto ilegível. Além disso, é um pouco específico para a situação atual: sea,b não vier do mesmo iterador, onde podemos aplicar esse tipo de conversão? (Esse código também tem o efeito colateral de ser muito complexo para o Intelli / J IDEA 2016.2, que o destaca como um erro no editor.)

  val (a2,b2) = (a,b).asInstanceOf[(T,C[T]) forSome {type T}]
  b2.f(a2)

Eu esperava que este funcionasse desdea2,b2 agora deve ter tiposT eC[T] para o mesmo existencialT. Mas temos um erro de compilação:

Error:(10, 9) type mismatch;
 found   : a2.type (with underlying type Any)
 required: T
  b2.f(a2)
       ^

Por quê? (Além disso, a abordagem tem a desvantagem de incorrer em custos de tempo de execução (eu acho) devido à criação e destruição de um par.)

  b match {
    case b : C[t] => b.f(a.asInstanceOf[t])
  }

Isso funciona. Mas encerrar o código com uma correspondência torna o código muito menos legível. (E também é muito complicado para Intelli / J.)

questionAnswers(4)

yourAnswerToTheQuestion