编写具有依赖于上下文绑定的选择的类型类

时间:2015-03-08 08:20:52

标签: scala shapeless

我的初始代码:

sealed trait Adder[L <: HList, U] extends DepFn2[L, Vector[U]]

object Adder {
  def apply[L <: HList, U: Ordering](implicit adder: Adder[L, U]): Aux[L, U, adder.Out] = adder

  type Aux[L <: HList, U, Out0] = Adder[L, U] { type Out = Out0 }

  implicit def found[T <: HList, U: Ordering]: Aux[Vector[U] :: T, U, Vector[U] :: T] =
    new Adder[Vector[U] :: T, U] {
      type Out = Vector[U] :: T
      def apply(l: Vector[U] :: T, collection: Vector[U]): Out = {
        (l.head ++ collection).sorted :: l.tail
      }
    }

  implicit def notFound[H, T <: HList, U: Ordering, OutT <: HList](implicit ut: Aux[T, U, OutT]): Aux[H :: T, U, H :: OutT] =
    new Adder[H :: T, U] {
      type Out = H :: OutT
      def apply(l: H :: T, collection: Vector[U]): Out = {
        val outT = ut(l.tail, collection)
        l.head :: outT
      }
    }

  implicit def empty[U: Ordering]: Aux[HNil, U, Vector[U] :: HNil] =
    new Adder[HNil, U] {
      type Out = Vector[U] :: HNil
      def apply(l: HNil, collection: Vector[U]): Out = collection :: HNil
    }
}

我发现了一个没有上下文限制的错误 Ordering,类型通过notFound而不是found传递, 这是不透明的。我尝试通过添加来修复错误 另一个隐含的,当没有Ordering时应该触发:

  implicit def foundNoOrdering[T <: HList, U]: Aux[Vector[U] :: T, U, Vector[U] :: T] =
    new Adder[Vector[U] :: T, U] {
      type Out = Vector[U] :: T
      def apply(l: Vector[U] :: T, collection: Vector[U]): Out = {
        l.head ++ collection :: l.tail
      }
    }

然而,这导致了一个模糊的隐含 foundNoOrderingfound。我怎样才能有不同的代码路径 取决于是否有Ordering

1 个答案:

答案 0 :(得分:3)

标准技巧是通过将隐含在祖先特征中来降低优先级

object Adder extends LowPriorityAdderImplicits {
   implicit def found...
}

trait LowPriorityAdderImplicits {
  implicit def foundNoOrdering....
}  

您会在标准库中找到一些。 LowPriorityImplicits似乎是名称中的习惯。

在规范中:

  • SLS§7.2隐式参数
  

如果有几个符合条件的参数与隐式匹配   参数的类型,将使用规则选择最具体的类型   静态重载决策(第6.26.3节)

  • SLS§6.26.3:相关位太长,无法完整引用,但您有一些关于
  • 的内容
  

类或对象C派生自类或对象D(如果其中之一)   以下是:

     

•C是D的子类,或

     

•C是从D或

派生的类的伴随对象      

•D是从中派生C的类的伴随对象。

并且派生出更具体的解决方案。我相信一个只是为了暗示。