找不到参数Mapper的隐式值



我试图创建一个简单的基于shapeless的函数,将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, None))
).build

我得到

找不到参数映射器的隐式值:shapeless.ops.hlist.mapper.Aux[s稳定器$1.csvMapper.type,Repr,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之外(使其路径稳定(。

相关内容

  • 没有找到相关文章

最新更新