返回使用派生特征的特征

时间:2014-01-08 22:18:05

标签: scala shapeless

我想创建一个知道如何返回HList以及派生HList的类型类。理想情况下,它将具有以下结构:

trait Axis[A, L1 <: HList] {
  type L2 <: Mapped[L1,Ordering]#Out
  def vectorize(a:A): L1
  def orderings: L2
}

并将像

一样实施
implicit object Tup2DI extends Axis[(Double, Int), Double :: Int :: HNil] {
  val m = implicitly[Mapped[Double :: Int :: HNil, Ordering]]
  type L2 = m.Out
  def vectorize(a: (Doubble, Int)) = a._1 :: a._2 :: HNil
  def orderings = implicitly[Ordering[Double]] :: implicitly[Ordering[Int]] :: HNil
}

问题是scala没有对类型进行更新,因此在编译期间,尽管有足够的信息来确定类型,但会导致此错误:

 found   : shapeless.::[Ordering[Double],shapeless.::[Ordering[Int],shapeless.HNil]]
 required: Tup2DI.L2
    (which expands to)  Tup2DI.m.Out
             def orderings:L2 = implicitly[Ordering[Double]] :: implicitly[Ordering[Int]] :: HNil

如何以正确编译的方式表达我关心的信息?

1 个答案:

答案 0 :(得分:0)

好的,在与#scala上知识渊博的人交谈之后,向我指出了以下工作:

trait Axis[A, L1 <: HList] {
  val L2: Mapped[L1,Ordering]
  def vectorize(a:A): L1
  def orderings: L2.Out
}
object Axis {
  def reifiedT[L1 <: HList](implicit M: Mapped[L1,Ordering]): Mapped[L1,Ordering] {
    type Out = M.Out
  } = M
}

implicit object Tup2DI extends Axis[(Double, Int), Double :: Int :: HNil] {
  val L2 = Axis.reifiedT[L]
  def vectorize(a: (Double, Int)) = a._1 :: a._2 :: HNil
  def orderings:L2.Out = implicitly[Ordering[Double]] :: implicitly[Ordering[Int]] :: HNil
}

显然你必须告诉scala明确设置已知的Out类型,这是Scalaz库中使用的一种技术。