【问题标题】:Shapeless - Apply factory functions with HListShapeless - 使用 HList 应用工厂函数
【发布时间】:2017-06-14 11:11:57
【问题描述】:

我有一堆工厂函数,它们都采用相同的参数并返回不同的类型。目前我明确地调用它们,但它非常冗长,我想将工厂泛化为HList,并通过映射HList来调用每个工厂。

case class Endpoint[A](a: A)

case class Factory[Ret](f: Int => Endpoint[Ret])

val factories = Factory[Int](a => Endpoint(a)) :: Factory[String](a => Endpoint(a.toString)) :: HNil

我已经定义了一个Poly1,这样我就可以映射我的HList 并为每个元素应用f

case class ApplyFactory(param: Int) extends Poly1 {
  implicit def generic[A]: Case.Aux[Factory[A], Endpoint[A]] =
    at((factory: Factory[A]) => factory.f(param))
}

val endpoints = factories.map(ApplyFactory(5))

问题在于could not find implicit value for parameter mapper。将ApplyFactory 更改为对象会使代码编译。如果Poly 被定义为类而不是对象,我如何映射HList?或者有没有更好的模式来应用具有给定参数集的函数 HList 并返回一个新的 HList 和结果?

【问题讨论】:

    标签: scala shapeless hlist


    【解决方案1】:

    不要打扰Poly,只需手动实现您需要的任何自定义地图:

    trait FactoryMap[L <: HList] {
      type Out <: HList
      def map(i: Int, h: L): Out
    }
    
    object FactoryMap {
      type Aux[L <: HList, O <: HList] = FactoryMap[L] { type Out = O }
    
      implicit def caseNil: Aux[HNil, HNil] = new FactoryMap[HNil] {
        type Out = HNil
        def map(i: Int, l: HNil): HNil = l
      }
    
      implicit def caseCons[T <: HList, O <: HList]
        (implicit ev: Aux[T, O]) = new FactoryMap[Factory[Int] :: T] {
          type Out = Endpoint[Int] :: O
          def map(i: Int, l: Factory[Int] :: T): Endpoint[Int] :: O = {
            val (h :: t) = l
            h.f(i) :: ev.map(i, t)
          }
        }
    }
    
    implicit case class MyMap[L <: HList](l: L) {
      def customMap[O <: HList](i: Int)(implicit ev: FactoryMap.Aux[L, O]): O =
        ev.map(i, l)
    }
    

    Poly 不同,将上述内容推广到任何Ret(而不是像我一样的Ret = Int)相对简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多