Som*_*ame 2 functional-programming scala generic-programming type-level-computation shapeless
我正在尝试实现用于获取第一个元素的通用函数:
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
}
Run Code Online (Sandbox Code Playgroud)
问题是编译器无法正确推断Repr
并将Tail
它们设置为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))
Run Code Online (Sandbox Code Playgroud)
修复它的解决方案是什么?以下肯定可以正常工作:
val a: Int = getFirst[(Int, Int, Int), Int, Int :: Int :: Int :: HNil, Int :: Int :: HNil]((1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
但这非常麻烦和丑陋。
解决方案是交换隐式参数顺序 -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
Run Code Online (Sandbox Code Playgroud)
我不知道这究竟是如何工作的,但我已经看到通过解析隐式来推断类型参数是从左到右工作的。
因此,使用您的签名,Scala 首先查找IsHCons.Aux[Repr, Head, Tail]
,但此时它并不知道太多Repr
,只是知道它是一个 HList。它发现了一些实例-也许这样的事情Nothing :: HList
,然后尝试去寻找Generic.Aux[A, Nothing :: HList]
(A
从推断input
),这将失败,因为这不是有效Generic
的A
。
归档时间: |
|
查看次数: |
84 次 |
最近记录: |