gpt4 book ai didi

scala - 如何在 Scala 中表达这种类型?存在类型类(即隐式)限制?

转载 作者:行者123 更新时间:2023-12-04 15:13:28 25 4
gpt4 key购买 nike

我正在使用 Play 框架的 JSON 库,它使用类型类来实现 Json.toJson function . (我可能会决定使用另一种静态类型较少的技术,比如反射;但现在我想使用这个库,因为它可以帮助我学习 Scala 类型系统。)

我有一堆简单的案例类需要传递给 toJson ,所以我必须实现一个隐式 Writes[T]他们每个人的对象。对于每个类,第一次剪辑可能看起来像这样。

// An example class
case class Foo(title: String, lines: List[String])

// Make 'Foo' a member of the 'Writes' typeclass
implicit object FooWrites extends Writes[Foo] {
def writes(f: Foo) : JsValue = {
val fields = Seq("title" -> toJson(f.title),
"lines" -> toJson(f.lines))
JsObject(fields)
}
}

每个类都有一个相似的隐含值,所以我可以抽象出公共(public)部分,如下所示。但这不会编译,因为我不确定如何声明类型。
def makeSimpleWrites[C](fields: (String, C => T??)*) : Writes[C] = {
new Writes[C] {
def writes(c: C) : JsValue = {
val jsFields = fields map { case (name, get) => (name, toJson(get(c)))}
JsObject(jsFields)
}
}
}

implicit val fooWrites : Writes[Foo] =
makeSimpleWrites[Foo]("title" -> {_.title}, "lines" -> {_.lines})
implicit val otherWrites ...

问题是类型 T我想传递给 makeSimpleWrites .它不能是普通类型参数,因为 fields 中的每个项目的 T 都不同.这是存在主义的类型吗?我还没有使用其中之一。在语法上挥舞...
def makeSimpleWrites[C](fields: (String, C=>T forSome { type T; implicit Writes[T] })*) 

这在 Scala 中可行吗?如果是这样,语法是什么?

最佳答案

因为每个字段都有不同的类型,所以每个字段都需要一个类型参数。这是因为要编写这些字段,您需要(隐式)提供 Writes对应类型的实例(到方法 toJson ),并且这些是静态解析的。

解决此问题的一种解决方案是将过程分为两部分:一种方法是您为每个字段调用以提取字段访问器并将其与相应的 WriteS 打包在一起。实例(这甚至可以从您已经通过的对子中进行隐式转换),以及一种方法,它采用整体并创建最终的 WriteS实例。像这样的东西(说明性,未经测试):

class WriteSFieldAccessor[C,T] private ( val title: String, val accessor: C => Any )( implicit val writes: Writes[T] )

implicit def toWriteSFieldAccessor[C,T:Writes]( titleAndAccessor: (String, C => T) ): WriteSFieldAccessor = {
new WriteSFieldAccessor[C,T]( titleAndAccessor._1, titleAndAccessor._2 )
}
def makeSimpleWrites[C](fields: WriteSFieldAccessor[C,_]*) : Writes[C] = {
new Writes[C] {
def writes(c: C) : JsValue = {
val jsFields = fields map { f: WriteSFieldAccessor =>
val jsField = toJson[Any](f.accessor(c))(f.writes.asInstanceOf[Writes[Any]])
(f.title, jsField)
}
JsObject(jsFields)
}
}
}

// Each pair below is implicitly converted to a WriteSFieldAccessor instance, capturing the required information and passing it to makeSimpleWrites
implicit val fooWrites : Writes[Foo] = makeSimpleWrites[Foo]("title" -> {_.title}, "lines" -> {_.lines})

有趣的部分是 toJson[Any](f.accessor(c))(f.writes..asInstanceOf[Writes[Any]]) .您只需通过 Any作为静态类型 但是 显式传递(通常是隐式的) Writes实例。

关于scala - 如何在 Scala 中表达这种类型?存在类型类(即隐式)限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13865947/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com