jed*_*sah 3 code-generation scala typeclass shapeless
我有一个json库,它通过遵循Scala中的类型类模式来定义(定义如何读取json)的概念 ReadCodec.该库使用Shapeless ' Typeclass构造来免费为任何案例类派生自动实例 ReadCodec.
现在,我有一个代码生成器,它在Scala中生成的类不是case类(但可能应该是).我可以让代码生成器为每个类生成ReadCodec实例,这就是我们现在所拥有的.但是现在如果我希望生成的类支持一些新的序列化形式,我需要修改代码生成以输出这个新类型类的实例.
有没有办法可以修改代码生成器来输出具有实例 LabelledGeneric或其他东西的类,这些实例可以利用生成(通过宏)案例类自动实例的机制?这样,生成的代码可以与使用Shapeless'的任何类型类模式互操作以Typeclass实现实例.
有一个棘手的步骤,但你绝对可以定义自己的LabelledGeneric实例.为了举例,我将使用Alex Archambault的argonaut-shapeless库,它不是字面上使用的TypeClass,但确实使用了LabelledGeneric,原理是一样的.
我们班的第一个:
class Foo(val i: Int, val s: String)
Run Code Online (Sandbox Code Playgroud)
那么对于我们的实例:
import shapeless._, labelled._, record._, syntax.singleton._
implicit object fooGeneric extends LabelledGeneric[Foo] {
val iw = Witness('i)
val sw = Witness('s)
type Repr = FieldType[iw.T, Int] :: FieldType[sw.T, String] :: HNil
def from(r: Repr): Foo = new Foo(r('i), r('s))
def to(t: Foo): Repr = ('i ->> t.i) :: ('s ->> t.s) :: HNil
}
Run Code Online (Sandbox Code Playgroud)
请注意,我们需要一种方法来引用记录键的单例类型Repr,因此我们首先定义几个见证.这是棘手的部分.
现在你只需写下:
import argonaut._, Argonaut._, Shapeless._
Run Code Online (Sandbox Code Playgroud)
然后:
scala> implicitly[EncodeJson[Foo]].encode(new Foo(42, "foo"))
res0: argonaut.Json = {"s":"foo","i":42}
Run Code Online (Sandbox Code Playgroud)
LabelledTypeClass如果你愿意,我可以把一个例子放在一起,但这个想法是完全一样的.
| 归档时间: |
|
| 查看次数: |
723 次 |
| 最近记录: |