私が取り組んでいるライブラリーについては、scalaクラスをシリアル化するための効率的で便利でタイプセーフなメソッドを提供する必要があります。理想は、ユーザーがケースクラスを作成できる場合であり、すべてのメンバーがシリアル化可能である限り、それもシリアル化可能であるように見えます。私はシリアル化と逆シリアル化の両方の段階でタイプを正確に知っているので、シリアル化形式の一部として「スキーマ」情報を持っている必要はありません(そしてそうする余裕はありません)(Javaオブジェクトのシリアル化のように)。
私はいくつかのアイデアで遊んでいますが、これはかなり近いようです。ここで私が目にする主な問題は、ユーザーがクラスの「適用」および「適用解除」機能をどのように指定する必要があるかということです。これらは本当に静的な関数なので、コンパイラーにそれを見つけてもらうことができるかどうか疑問に思います。
これが自己完結型の例です:
trait InOut[T] {
// just keeping things simple, for illustration purposes
def toWire(x: T): Array[Byte]
def fromWire(v: Array[Byte] ): T
}
object InOutConversions {
// Pretend these are implemented properly
implicit def Int = new InOut[Int] {
def toWire(x: Int): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): Int = 44
}
implicit def String = new InOut[String] {
def toWire(x: String): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): String = "blah"
}
// etc... for all the basic types
}
そして、私はこのような関数が必要です:
def serialize2[T, A1 : InOut, A2 : InOut](unapply : T => Option[Product2[A1, A2]])(obj : T) : Array[Byte] = {
val product : Product2[A1, A2] = unapply(obj).get
implicitly[InOut[A1]].toWire(product._1) ++ implicitly[InOut[A2]].toWire(product._2)
}
これにより、ユーザーは非常に簡単に使用できるようになります。例えば
case class Jesus(a: Int, b: String)
val j = Jesus(4, "Testing")
serialize2 (Jesus.unapply(_)) (j)
しかし、ご覧のとおり、その最後の行は本当にかなり厄介でした。確かにそれを改善することは可能でなければなりませんか?(イエスを考えると、確かに私は「適用されない」静的メソッドを見つけることができます)