gpt4 book ai didi

scala - 如何使用 Shapeless 或 Macro 将 Scala 案例类字段和值作为(字符串,字符串)获取

转载 作者:行者123 更新时间:2023-12-04 07:40:02 24 4
gpt4 key购买 nike

几天来,我一直在努力尝试创建一个宏或使用 shapeless 创建一个方法/函数来提取字段名称和值作为元组 [String, String]。
让我们想象以下案例类:

case class Person(name: String, age: Int)
我想要这样的东西(在案例类中并不需要真正成为一种方法)。
case class Person(name: String, age: Int) {
def fields: List[(String, String)] = ???
}

// or

def fields[T](caseClass: T): List[(String, String)] = ???
我在这里看到了很多类似的解决方案,但我无法让它与我的 (String, String) 用例一起使用
我也很欣赏一些文献来学习和扩展我关于宏的知识,我有 Scala 编程(马丁第三版)和 Scala 编程(O'REILLY - Dean Wampler 和 Alex Payne),只有 O'REILLY 有一个非常小的关于宏的章节,老实说它非常缺乏。
谢谢!
PD:我使用的是 Scala 2.12.12,所以我没有那些用于案例类的花哨的新方法 产品元素名称 这样的:(

最佳答案

基于 LabelledGenericKeys类型类

import shapeless.LabelledGeneric
import shapeless.HList
import shapeless.ops.hlist.ToTraversable
import shapeless.ops.record.Keys

case class Person(name: String, age: Int)

def fields[P <: Product, L <: HList, R <: HList](a: P)(
implicit
gen: LabelledGeneric.Aux[P, L],
keys: Keys.Aux[L, R],
ts: ToTraversable.Aux[R, List, Symbol]
): List[(String, String)] = {
val fieldNames = keys().toList.map(_.name)
val values = a.productIterator.toList.map(_.toString)
fieldNames zip values
}

fields(Person("Jean-Luc, Picard", 70))
// : List[(String, String)] = List((name,Jean-Luc, Picard), (age,70))
scastie

IDEA ... shows an error ... No implicit arguments


IntelliJ 编辑器中的错误突出显示是 sometimes对于类型级代码和宏,不是 100% 准确。最好将其视为指导,并适当信任 Scala 编译器,因此,如果编译器满意但 IJ 不满意,则使用编译器。另一种选择是尝试 Scala Metals它应该在编译器诊断和编辑器内错误突出显示之间具有一对一的映射。

why you used LabelledGeneric.Aux, Keys.Aux, ToTraversable.Aux


这是使用称为类型类的设计模式。我的建议是通过 The Type Astronaut's Guide to Shapeless特别是关于 Chaining dependent functions 的部分

Dependently typed functions provide a means of calculating one typefrom another. We can chain dependently typed functions to performcalculations involving multiple steps.


考虑以下类型之间的依赖关系
                input type
|
gen: LabelledGeneric.Aux[P, L],
|
output type

input type
|
keys: Keys.Aux[L, R]
|
output type
请注意例如输出类型 LLabelledGeneric成为 Keys的输入类型.通过这种方式,您向编译器展示了类型之间的关系,作为返回,编译器能够为您提供 HList代表来自 Product 的字段名称代表特定的案例类,以及在程序运行之前的所有这些。 ToTraversable需要这样你才能找回一个普通的 Scala List来自 HList启用以下位
.toList.map(_.name)
希望这至少能给你一点方向。要搜索的一些关键字是:类型类、依赖类型、隐式解析、类型别名 Aux pattern , 类型成员 vs 类型参数, type refinement等 Typelevel 社区新增 Discord channel在那里你可以得到进一步的方向。

关于scala - 如何使用 Shapeless 或 Macro 将 Scala 案例类字段和值作为(字符串,字符串)获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67532242/

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