【问题标题】:Shapeless type inference for HList does not workHList 的无形类型推断不起作用
【发布时间】:2020-04-06 15:23:21
【问题描述】:

我正在尝试实现获取第一个元素的通用函数:

import shapeless.ops.hlist.IsHCons
import shapeless.{Generic, HList}

object App {

  def main(args : Array[String]) {
    val a: Int = getFirst((1, 2, 3))
    val b: String = getFirst(("a", "b", 10, 45, "aaa"))
  }

  def getFirst[A, Head, Repr <: HList, Tail <: HList](input: A)
                                                     (implicit hcons: IsHCons.Aux[Repr, Head, Tail],
                                                      gen: Generic.Aux[A, Repr]): Head = gen.to(input).head
}

问题是编译器无法正确推断ReprTail 并将它们设置为Nothing。就是这样:

Error:(9, 26) could not find implicit value for parameter gen: shapeless.Generic.Aux[(Int, Int, Int),Repr]
    val a: Int = getFirst((1, 2, 3))
Error:(9, 26) not enough arguments for method getFirst: (implicit hcons: shapeless.ops.hlist.IsHCons.Aux[Nothing :: Nothing,Head,Tail], implicit gen: shapeless.Generic.Aux[(Int, Int, Int),Nothing :: Nothing])Head.
Unspecified value parameter gen.
    val a: Int = getFirst((1, 2, 3))
Error:(10, 29) could not find implicit value for parameter gen: shapeless.Generic.Aux[(String, String, Int),Repr]
    val b: String = getFirst(("a", "b", 10))
Error:(10, 29) not enough arguments for method getFirst: (implicit hcons: shapeless.ops.hlist.IsHCons.Aux[Nothing :: Nothing,Head,Tail], implicit gen: shapeless.Generic.Aux[(String, String, Int),Nothing :: Nothing])Head.
Unspecified value parameter gen.
    val b: String = getFirst(("a", "b", 10))

有什么办法可以解决这个问题?以下肯定可以正常工作:

val a: Int = getFirst[(Int, Int, Int), Int, Int :: Int :: Int :: HNil, Int :: Int :: HNil]((1, 2, 3))

但是这样非常麻烦和丑陋。

【问题讨论】:

    标签: scala functional-programming generic-programming shapeless type-level-computation


    【解决方案1】:

    解决方案是交换隐式参数顺序 - 首先是Generic,其次是IsHCons

      def getFirst[A, Head, Repr <: HList, Tail <: HList](input: A)
                                                         (implicit gen: Generic.Aux[A, Repr], hcons: IsHCons.Aux[Repr, Head, Tail]
                                                          ): Head = gen.to(input).head
    

    (scastie)

    我不知道这到底是如何工作的,但我已经看到通过解析隐式来推断类型参数从左到右工作。

    因此,使用您的签名,Scala 首先查找IsHCons.Aux[Repr, Head, Tail],但此时它对Repr 知之甚少,只知道它是一个HList。它找到 some 实例 - 可能是 Nothing :: HList,然后尝试查找 Generic.Aux[A, Nothing :: HList]A 是从 input 推断出来的),但由于这不是有效的 @ 而失败了987654331@ 为A

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2014-06-03
      • 2021-02-18
      • 1970-01-01
      • 2017-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多