如何解决找不到参数映射器的隐式值
我尝试创建一个简单的基于无形的函数,将 case 类转换为字符串列表,然后我可以将其编码为 csv。
这样做的目的是在 case 类的每个成员上调用类型类 CsvEncoder
,然后调用方法 encode
将其更改为字符串。
类型类:
trait CsvEncoder[T] {
def encode(t: T): String
}
trait LowPriorityEncoder {
implicit def genericEncoder[T]: CsvEncoder[T] = _.toString
}
object CsvEncoder extends LowPriorityEncoder {
implicit def optionEncoder[T](
implicit e: CsvEncoder[T]
): CsvEncoder[Option[T]] = _.fold("")(e.encode)
}
而且无形:
class CsvBuilder[Row](rows: List[Row]) {
object csvMapper extends Poly1 {
implicit def caseEncode[V](
implicit e: CsvEncoder[V]
): Case.Aux[FieldType[Symbol,V],FieldType[Symbol,String]] =
at[FieldType[Symbol,V]](s => field[Symbol](e.encode(s)))
}
def build[Repr <: HList,OutRepr <: HList](
implicit labelledGeneric: LabelledGeneric.Aux[Row,Repr],mapper: Mapper.Aux[csvMapper.type,Repr,OutRepr],toMap: ToMap.Aux[OutRepr,Symbol,String]
): List[Map[String,String]] = {
def transform(row: Row): Map[String,String] = {
val formattedRows = labelledGeneric
.to(row)
.map(csvMapper)
val fields = toMap(formattedRows)
.map {
case (k: Symbol,value: String) =>
(k.toString -> value)
}
fields
}
rows.map(transform(_))
}
}
当我尝试使用简单的案例类时:
final case class ProjectCsvRow(
project: Option[String],something: Option[String],site: Option[String],state: Option[Int]
)
new CsvBuilder[ProjectCsvRow](
List(ProjectCsvRow(Some(""),None,None))
).build
我要了
找不到参数映射器的隐含值:shapeless.ops.hlist.Mapper.Aux[stabilizer$1.csvMapper.type,OutRepr]
我想我错过了一些东西,但我真的想不通。
我已经检查过每个字段是否都有 CsvEncoder
的实例。
解决方法
首先,您的 Poly
不正确。 Symbol
类型太粗糙。记录的键不仅仅是 Symbol
,它们是 Symbol
的单例子类型。你应该定义
object csvMapper extends Poly1 {
implicit def caseEncode[K <: Symbol,V](
implicit e: CsvEncoder[V]
): Case.Aux[FieldType[K,V],FieldType[K,String]] =
at[FieldType[K,V]](s => field[K](e.encode(s)))
}
其次,将 Poly
嵌套到类(而不是对象)中可能很危险(它开始依赖于 CsvBuilder
的实例,因此依赖于类型 Row
)。因此将 csvMapper
移到 CsvBuilder
之外(使其路径稳定)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。