Сворачивание предоставленного HList - PullRequest
0 голосов
/ 18 мая 2018

Я знаю, что моей проблемой может быть "проблема 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

Мой вопрос:

a) Как я могу решить эту проблему компиляции, или

b)Есть ли другой / лучший способ решить мою начальную проблему

Редактировать

Оказывается, моя ошибка была вызвана неправильным импортом, я как-то импортировал tuple.LeftFolder вместоhlist.LeftFolder, глупая ошибка

1 Ответ

0 голосов
/ 19 мая 2018

Следующий код компилируется

  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)
...