是否可以仅使用不带TypeTags的多态函数重写以下示例?该示例包含一个类A[T]
,当应用于具有相同类型参数matches
和{{true
的{{1}}实例时,该方法A
返回T
1}}如果此类型参数具有不同的值。然后将false
映射到matches
{h} {h} {名}}的hlist,从而生成嵌套hlists的列表,其中包含将l
的每个项目与其他项目匹配的结果:
A[T]
每个项目都有一个匹配项,即结果为:
l
当我尝试重写没有TypeTags的示例时,import scala.reflect.runtime.universe._
import shapeless._
class A[T: TypeTag]{
object matches extends Poly1 {
implicit def default[U: TypeTag] = at[A[U]]{ _ => typeOf[U] <:< typeOf[T] }
}
}
val l = new A[Int] :: new A[String] :: new A[Boolean] :: HNil
object matcher extends Poly1 {
implicit def default[T] = at[A[T]]{ a => l map a.matches }
}
l map matcher
总是使用它的(true :: false :: false :: HNil) ::
(false :: true :: false :: HNil) ::
(false :: false :: true :: HNil) :: HNil
大小写并返回false:
matches
结果是:
no
是否可以在没有TypeTags的情况下重写此示例,并获得与第一种情况相同的结果?
答案 0 :(得分:2)
看起来你真的希望能够部分应用更高级别的功能来干净地解决这个问题。开箱即用的任何一种好的语法都不可能实现这一点,但我once wrote some code可以帮助它变得更容易(注意这都是1.2.4):
import shapeless._
trait ApplyMapper[HF, A, X <: HList, Out <: HList] {
def apply(a: A, x: X): Out
}
object ApplyMapper {
implicit def hnil[HF, A] = new ApplyMapper[HF, A, HNil, HNil] {
def apply(a: A, x: HNil) = HNil
}
implicit def hlist[HF, A, XH, XT <: HList, OutH, OutT <: HList](implicit
pb: Poly.Pullback2Aux[HF, A, XH, OutH],
am: ApplyMapper[HF, A, XT, OutT]
) = new ApplyMapper[HF, A, XH :: XT, OutH :: OutT] {
def apply(a: A, x: XH :: XT) = pb(a, x.head) :: am(a, x.tail)
}
}
请参阅上面链接的答案。
这允许您编写以下内容:
class A[T]
object matches extends Poly2 {
implicit def default[T, U](implicit sub: U <:< T = null) =
at[A[T], A[U]]((_, _) => Option(sub).isDefined)
}
object mapMatcher extends Poly1 {
implicit def default[T, X <: HList, Out <: HList](
implicit am: ApplyMapper[matches.type, A[T], X, Out]
) = at[(A[T], X)] { case (a, x) => am(a, x) }
}
val l = new A[Int] :: new A[String] :: new A[Boolean] :: HNil
可能有一个更好的解决方案,但目前我只有一分钟的时间做出回应,它的工作原理如下:
scala> l.zip(l mapConst l).map(mapMatcher).toList.foreach(println)
true :: false :: false :: HNil
false :: true :: false :: HNil
false :: false :: true :: HNil
根据需要。