我希望能够将Function1[I, ?]的任意列表应用于任意输入的I。这是我到目前为止的内容:

    type StringInputFunction[T] = Function[String, T]

    val strLen: String => Int = _.length
    val strRev: String => String = _.reverse

    val functions = strLen :: strRev :: HNil
    val expected = 4 :: "evif" :: HNil

    object applyTo5 extends (StringInputFunction ~> Id) {
      override def apply[T](f: StringInputFunction[T]): Id[T] = f("five")
    }
    def applyFunctionsTo5[FH <: HList, OH <: HList](fs: FH)
        (implicit constrain: UnaryTCConstraint[FH, StringInputFunction],
         mapper: Mapper.Aux[applyTo5.type, FH, OH]): mapper.Out = {
      fs.map(applyTo5)
    }
    applyFunctionsTo5(functions) shouldBe expected

    class ApplyTo(string: String) extends (StringInputFunction ~> Id) {
      override def apply[T](f: StringInputFunction[T]): Id[T] = f(string)
    }
    def applyFunctionsTo[FH <: HList, OH <: HList]
        (fs: FH, input: String)
        (implicit constrain: UnaryTCConstraint[FH, StringInputFunction],
         mapper: Mapper.Aux[ApplyTo, FH, OH]): mapper.Out = {
      val applyTo = new ApplyTo(input)
      fs.map(applyTo)
    }
    applyFunctionsTo(functions, "five") shouldBe expected

这导致编译错误:
ShapelessSpec.scala:81: could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[applyTo.type,FH]
      fs.map(applyTo)
ShapelessSpec.scala:83: could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper.Aux[ApplyTo,shapeless.::[String => Int,shapeless.::[String => String,shapeless.HNil]],OH]
    applyFunctionsTo(functions, "five") shouldBe expected
  • 如何解决此问题,使其可与任何String输入配合使用?
  • 我可以进一步更改通用化,使其与任何T输入类型一起使用吗?
  • 最佳答案

    我以为我以前做过这种精确的操作,几年前就能够找到this gist。总结一下我的示例,您可以仅使用Shapeless已经提供的操作就可以很好地做到这一点,其方式看起来很像您将如何使用值列表中的普通列表执行类似的操作。假设您具有以下设置:

    import shapeless.{ ::, HNil }
    
    val strLen: String => Int = _.length
    val strRev: String => String = _.reverse
    
    val functions = strLen :: strRev :: HNil
    

    然后,您可以编写以下代码:
    scala> functions.zipApply(functions.mapConst("five"))
    res0: Int :: String :: shapeless.HNil = 4 :: evif :: HNil
    

    或这个:
    scala> def foo(in: String) = functions.zipApply(functions.mapConst(in))
    foo: (in: String)Int :: String :: shapeless.HNil
    
    scala> foo("six")
    res1: Int :: String :: shapeless.HNil = 3 :: xis :: HNil
    

    这将适用于来自应用于该特定类型的特定类型的任何函数列表。

    要点给出了几种替代方法,但是zipApplymapConst对我而言感觉最好。

    关于scala - 如何将任意函数列表应用于任意值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56689313/

    10-12 23:21