我目前正在实现一个库来对XML-RPC消息进行序列化和反序列化。这几乎完成,但现在我试图删除我当前的样板使用方法无形。我当前的代码:如何使用属性和类型类构造不成形的case类?
trait Serializer[T] {
def serialize(value: T): NodeSeq
}
trait Deserializer[T] {
type Deserialized[T] = Validation[AnyErrors, T]
type AnyErrors = NonEmptyList[AnyError]
def deserialize(from: NodeSeq): Deserialized[T]
}
trait Datatype[T] extends Serializer[T] with Deserializer[T]
// Example of asProduct, there are 20 more methods like this, from arity 1 to 22
def asProduct2[S, T1: Datatype, T2: Datatype](apply: (T1, T2) => S)(unapply: S => Product2[T1, T2]) = new Datatype[S] {
override def serialize(value: S): NodeSeq = {
val params = unapply(value)
val b = toXmlrpc(params._1) ++ toXmlrpc(params._2)
b.theSeq
}
// Using scalaz
override def deserialize(from: NodeSeq): Deserialized[S] = (
fromXmlrpc[T1](from(0)) |@| fromXmlrpc[T2](from(1))
) {apply}
}
我的目标是让我的媒体库的用户序列化/反序列化的情况下类,而不必强迫他写的样板代码。目前,您必须使用前面提到的asProduct方法来声明案例类和一个隐式的val,以便在上下文中具有一个Datatype实例。这种隐含在以下代码中使用:
def toXmlrpc[T](datatype: T)(implicit serializer: Serializer[T]): NodeSeq =
serializer.serialize(datatype)
def fromXmlrpc[T](value: NodeSeq)(implicit deserializer: Deserializer[T]): Deserialized[T] =
deserializer.deserialize(value)
这是序列化和使用类型类解串的经典的策略。
在这一刻,我已经掌握了如何从案例类HList通过通用或LabelledGeneric转换。问题是一旦我完成了这个转换,我可以像在asProduct2的例子中一样,调用方法fromXmlrpc和toXmlrpc。我没有关于案例类中属性类型的任何信息,因此,编译器找不到任何隐含的,从Xmlrpc和到Xmlrpc满足。我需要一种方法来限制一个HList的所有元素在上下文中都有一个隐含的数据类型。
由于我是一名无形的初学者,我想知道获得此功能的最佳方式是什么。我有一些见解,但我绝对不知道如何使用无形来完成它。理想情况是有办法从案例类的给定属性获取类型,并将其明确地从0xmlrpc和转换为,并将其类型传递给0xmlrpc。我想这不是如何做到的。