【问题标题】:How to apply a separate function to each index of a known Shapelss HList如何将单独的函数应用于已知 Shapelss HList 的每个索引
【发布时间】:2020-12-09 04:22:18
【问题描述】:

我知道 HList 的类型,我想将特定函数应用于 HList 中的每个特定项。例如。

我知道 HList 的类型,在本例中为 String :: Int :: String :: HNil

val values = "Hello World" :: 5 :: "Goodbye World" :: HNil

所以我从 type => Int 为每个项目创建一个函数。

val funcs =
  ((_: String) => 1) ::
  ((_: Int) => 2) ::
  ((_: String) => 3) ::
   HNil

我想对列表中的每个项目应用函数 1 到值 1,函数 2 到值 2,等等。这是对函数签名的最佳猜测。 V

// V are the Values of type String :: Int :: String :: HNil
// F are the Functions of type (String => Int) :: (Int => Int) :: (String => Int) :: HNil
// R is the Int Results of type Int :: Int :: Int :: HNil
def applyFunction[V <: HList, F <: HList, R <: HList](v: V, f: F)(
   implicit ev: V =:= F,
   utcc: UnaryTCConstraint[F, Function[*, Int]]
): R

现在我正在为如何实际实现这个功能而苦苦挣扎,或者也许 Shapeless 已经有了可以做到这一点的东西。

【问题讨论】:

    标签: scala shapeless


    【解决方案1】:

    this SO answer 为灵感,我想出了以下几点:

    import shapeless._
    
    val values = "Hello World" :: 5 :: "Goodbye World" :: HNil
    
    val funcs = ((_: String) => 1) ::
                ((_: Int) => 2) ::
                ((_: String) => 3) :: HNil
    
    object applyTo extends Poly1 {
      implicit def caseInt = at[(Int=>Int,Int)]      {case (f,v) => f(v)}
      implicit def caseStr = at[(String=>Int,String)]{case (f,v) => f(v)}
    }
    
    funcs.zip(values).map(applyTo)
    //1 :: 2 :: 3 :: HNil: Int :: Int :: Int :: shapeless.HNil
    

    【讨论】:

    • 不幸的是,我必须为每种类型添加一个 poly case。如果引入了另一种数据类型,则不必在 applyTo 中添加案例会很好。这个世界上有很多数据类型。然而,这是一个很好的开始。
    【解决方案2】:

    您可以使用标准类型类shapeless.ops.hlist.ZipApply

    funcs.zipApply(values) // 1 :: 2 :: 3 :: HNil
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-16
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 2017-05-24
      • 2017-06-07
      相关资源
      最近更新 更多