Построить список экземпляров классов типов для типа HList - PullRequest
1 голос
/ 07 марта 2020

Я пытаюсь улучшить типы для одного из наших API. Я хочу создать сборщик данных со следующей подписью:

def runIt[T <: HList](id: Int): T = ???

Он должен извлечь вызов внешнего сервера для некоторого объекта и вернуть HList с необходимыми данными. Первая задача - создать список параметров API для необходимых функций.

Вот что я сделал:

import shapeless._
import shapeless.ops.hlist._

trait Feature

trait FeatureFetcher[T] {
  def name: String
}

trait F1 extends Feature
trait F2 extends Feature

implicit case object f1Fetcher extends FeatureFetcher[F1] {
  val name = "f1name"
}

implicit case object f2Fetcher extends FeatureFetcher[F2] {
  val name = "f2name"
}

def makeIt[T <: HList](id: Int)
                      (implicit liftAll: LiftAll[FeatureFetcher, T]) = {

  // I need this, but it does not compile here
  // liftAll.instances.toList.map(_.name).mkString(",")

  liftAll.instances
}

makeIt[F1 :: F2 :: HNil](1).toList.map(_.name).mkString(",")

Это действительно работает. Но когда я перемещаю .toList в makeIt функцию, я получаю ошибку

Error:(25, 21) could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[liftAll.Out,List,Lub]
liftAll.instances.toList.map(_.name).mkString(",")

Как решить эту проблему?

Ответы [ 2 ]

1 голос
/ 07 марта 2020

Я думаю, что когда код вызывает неявный экземпляр с implicit liftAll: LiftAll[FeatureFetcher, T], зависимый тип Out of LiftAll теряется, поэтому компилятор не знает, какой именно тип экземпляров вернется, и, следовательно, ошибка.

Возможное решение может заключаться в использовании, используйте его the из shapeless, который, как предполагается, неявно лучше.

the[liftAll].instances.toList

Дайте мне знать, если ut помогает !!

0 голосов
/ 07 марта 2020

На основе segeljakt , попробуйте передать liftAll.Out на ToTraversable.Aux через LiftAll.Aux, например,

def makeIt[In <: HList, Out <: HList](id: Int)(implicit
  liftAll: LiftAll.Aux[FeatureFetcher, In, Out],
  toTraversable: ToTraversable.Aux[Out, List, FeatureFetcher[_]]
): String = {
  liftAll.instances.toList.map(_.name).mkString(",")
}

type In = F1 :: F2 :: HNil
type Out = FeatureFetcher[F1] :: FeatureFetcher[F2] :: HNil
makeIt[In, Out](1)
// res1: String = f1name,f2name

или на основе ToElmTypes

case class MakeIt[In <: HList]() {
  def apply[Out <: HList](id: Int)(implicit
    liftAll: LiftAll.Aux[FeatureFetcher, In, Out],
    toTraversable: ToTraversable.Aux[Out, List, FeatureFetcher[_]]
  ): String = {
    liftAll.instances.toList.map(_.name).mkString(",")
  }
}

MakeIt[F1 :: F2 :: HNil].apply(1)
...