为什么这会按预期工作:
def method1[L <: HList, M <: HList, F, R](list: L)(builder: F)
(implicit ev: Comapped.Aux[L, Seq, M],
fntp: FnToProduct.Aux[F, M => R]) = println("asd")
method1(Seq("asd") :: HNil) { (s: String) =>
6
}
但这不是吗?
def method2[L <: HList, M <: HList, F, R](list: L)(builder: F)
(implicit ev: Comapped.Aux[L, Seq, M],
fntp: FnToProduct.Aux[F, M => Seq[R]]) = println("asd")
method2(Seq("asd") :: HNil) { (s: String) =>
Seq(6)
}
似乎在FnToProduct.Aux的返回类型中添加一个类型构造函数会破坏它。
答案 0 :(得分:3)
问题在于,当编译器试图推断method1
的类型参数时,它会找到L
和M
以及F
没有问题,但是然后当它到达R
时,它无法判断FnToProduct.Aux
的第二个参数是否具有与M => Seq[R]
对齐的正确形状。
在我的脑海中,我没有很好地解释为什么在第二种情况下发生这种情况而不是第一种情况,但这是一个经常遇到的限制,并且有一些解决方法。
第一种方法是完全离开Aux
FnToProduct
。根据您的实际方法正在做什么,这可能没问题,但如果您需要明确地引用R
,它将不起作用。
第二种解决方法是推断第二种类型参数的返回类型,然后要求证明它是Seq
:
import shapeless._, ops.function.FnToProduct, ops.hlist.Comapped
def method2[L <: HList, M <: HList, F, S, R](list: L)(builder: F)
(implicit
ev: Comapped.Aux[L, Seq, M],
fntp: FnToProduct.Aux[F, M => S],
s: S <:< Seq[R]
) = println("asd")
method2(Seq("asd") :: HNil) { (s: String) => Seq(6) }
这是一个额外的语法噪音,但它有效。