Сворачивание по предоставленному HList
Я осознаю, что моей проблемой может быть "проблема XY", поэтому вот краткое резюме того, чего я хочу достичь. Допустим, у меня есть следующий тип:
trait Provider[T] { def provide: T }
Я хочу иметь возможность объединить несколько значений, предоставленных из этого типа, в одно (каждое из них может иметь различный тип). Комбинация происходит в другой части программы, давайте определим тип Combiner (попытался применить бесформенный к моей проблеме):
trait Combiner[Out, Providers <: HList] {
def combine(providers: Providers): Out
}
Я придумал следующее:
class ShapelessCombiner[Out, Providers <: HList, P](implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, P, Out]
) extends Combiner[Out, Providers] {
def combine(providers: Providers): Out = folder(folder, zero)
}
Чтобы указать, какая функция используется для свертывания, я создал вспомогательный метод:
def shapelessCombiner[Out, Providers <: HList](
fun: Poly
)(implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, fun.type, Out]
) = new ShapelessCombiner[Out, Providers]
Все хорошо, кроме того, что это не работает. Я пытался проверить это, используя следующий код:
implicit val zero = Json.obj()
//incorrect implementation, but compilation is important here
object poly extends Poly2 {
implicit def caseInt =
at[Json, Provider[Int]]((j, p) => j deepMerge Json.fromInt(p.provide))
implicit def caseString =
at[Json, Provider[String]]((j, p) => j deepMerge Json.fromString(p.provide))
}
def hlistInstance: Provider[Int] :: Provider[String] :: HNil = ???
val directResult = hlistInstance.foldLeft(zero)(poly) //compiles
val combiner = shapelessCombiner[Json, Provider[Int] :: Provider[String] :: HNil](poly)//do not compile, LeftFolder.AUX not found
Мой вопрос:
а) Как я могу решить эту проблему, или
б) Есть ли другой / лучший способ решить мою начальную проблему
редактировать
Оказывается, моя ошибка была вызвана неправильным импортом, я как-то импортировал tuple.LeftFolder вместо hlist.LeftFolder, глупая ошибка
1 ответ
Следующий код компилируется
import io.circe.Json
import shapeless.{::, HList, HNil, Poly, Poly2}
import shapeless.ops.hlist.LeftFolder
trait Provider[T] {
def provide: T
}
trait Combiner[Out, Providers <: HList] {
def combine(providers: Providers): Out
}
class ShapelessCombiner[Out, Providers <: HList, P](implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, P, Out]
) extends Combiner[Out, Providers] {
def combine(providers: Providers): Out = folder(providers, zero)
}
def shapelessCombiner[Out, Providers <: HList](
fun: Poly
)(implicit
zero: Out,
folder: LeftFolder.Aux[Providers, Out, fun.type, Out]
) = new ShapelessCombiner[Out, Providers, fun.type]
implicit val zero = Json.obj()
object poly extends Poly2 {
implicit def caseInt =
at[Json, Provider[Int]]((j, p) => j deepMerge Json.fromInt(p.provide))
implicit def caseString =
at[Json, Provider[String]]((j, p) => j deepMerge Json.fromString(p.provide))
}
def hlistInstance: Provider[Int] :: Provider[String] :: HNil = ???
val directResult = hlistInstance.foldLeft(zero)(poly)
val combiner = shapelessCombiner[Json, Provider[Int] :: Provider[String] :: HNil](poly)