无形:FnToProduct无法使用Type构造函数

时间:2016-10-10 16:56:24

标签: scala shapeless

为什么这会按预期工作:

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的返回类型中添加一个类型构造函数会破坏它。

1 个答案:

答案 0 :(得分:3)

问题在于,当编译器试图推断method1的类型参数时,它会找到LM以及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) }

这是一个额外的语法噪音,但它有效。