Search code examples
scalapattern-matchingtype-erasure

Getting around a type-erasure in pattern-matching


I am trying to work around a type erasure in pattern matching. Assuming:

import java.io._

trait Serializer[V] {
  def save(os: OutputStream, v: V): Unit
  def load(in: InputStream): V
}

trait HasSerializer[V] { def serializer: Serializer[V] }

How can I get this to compile without warning and without asInstanceOf:

def test[V](os: OutputStream, v: V): Unit = v match {
  case hs: HasSerializer[V] => hs.serializer.save(os, v)
  case _                    => ???
}

? test is called with a value from a map and there is no means to provide a class manifest.

Any fancy extractor trick maybe?


Solution

  • Well the question has kind of a wrong precondition (as I just realize) -- we can take Serializer apart into a serializer and a deserializer. Obviously, when I have an instance of V, my use case is serialization, and that doesn't require V as a return type. Thus

    trait Serializer { def save(os: OutputStream): Unit }
    

    would suffice, and any type can mix that in. And do:

    def testSer[V](os: OutputStream, v: V): Unit = v match {
      case s: Serializer => s.save(os)
      case _ => new ObjectOutputStream(os).writeObject(v)
    }
    

    And for deserialization, we would either provide the deserializer along with the construction of a Ref[V], or rely on class lookup through ObjectInputStream.