HList上的约束:检查类型的单次出现

时间:2016-08-30 11:22:17

标签: scala shapeless

我正在尝试在HList上添加约束(来自Shapeless):

  • 它应包含任意数量的TA类型的元素(从0到N);
  • 它应该包含一个且只有一个TB类型的元素。

我的示例有这种类型层次结构:

trait T
case class TA extends T
case class TB extends T

举例:

  • tb :: HNil有效
  • ta :: tb ::HNil有效
  • ta :: tb :: ta :: HNil有效
  • ta :: HNil无效
  • HNil无效

我无法弄清楚如何将其表达为约束。

1 个答案:

答案 0 :(得分:9)

您可以使用自定义类型类来执行此操作,该类可以确定只有一个CId Rate FDateTime 109 6 2016-08-09 20:37:33.643 ,而所有其他元素都是TB。如果你想象归纳地建立这个列表,你会发现你需要处理两个案例 - 你到目前为止所看到的一切都是TA(我们可以见证TA 1}})当前元素是ToList[T, TA],或者您已经看过一个TB,当前元素是TB

TA

然后:

import shapeless._, ops.hlist.{ ToList }

trait T
case class TA() extends T
case class TB() extends T

trait UniqueTB[L <: HList] extends DepFn1[L] {
  type Out = TB
  def apply(l: L): TB
}

object UniqueTB {
  def apply[L <: HList](implicit utb: UniqueTB[L]): UniqueTB[L] = utb
  def getTB[L <: HList](l: L)(implicit utb: UniqueTB[L]): TB = utb(l)

  implicit def firstTB[T <: HList](
    implicit tl: ToList[T, TA]
  ): UniqueTB[TB :: T] = new UniqueTB[TB :: T] {
    def apply(l: TB :: T): TB = l.head
  }

  implicit def afterTB[T <: HList](
    implicit utb: UniqueTB[T]
  ): UniqueTB[TA :: T] = new UniqueTB[TA :: T] {
    def apply(l: TA :: T): TB = utb(l.tail)
  }
}

我已经为类型类提供了一个返回scala> UniqueTB[TB :: HNil] res0: UniqueTB[shapeless.::[TB,shapeless.HNil]] = UniqueTB$$anon$1@385c6929 scala> UniqueTB[TA :: TB :: HNil] res1: UniqueTB[shapeless.::[TA,shapeless.::[TB,shapeless.HNil]]] = UniqueTB$$anon$2@682dd97e scala> UniqueTB[TA :: TB :: TA :: HNil] res2: UniqueTB[shapeless.::[TA,shapeless.::[TB,shapeless.::[TA,shapeless.HNil]]]] = UniqueTB$$anon$2@5ef48f82 scala> UniqueTB[TB :: HNil] res3: UniqueTB[shapeless.::[TB,shapeless.HNil]] = UniqueTB$$anon$1@33be241 scala> UniqueTB[TA :: HNil] <console>:25: error: could not find implicit value for parameter utb: UniqueTB[shapeless.::[TA,shapeless.HNil]] UniqueTB[TA :: HNil] ^ scala> UniqueTB[HNil] <console>:25: error: could not find implicit value for parameter utb: UniqueTB[shapeless.HNil] UniqueTB[HNil] ^ scala> UniqueTB[TB :: TB :: HNil] <console>:25: error: could not find implicit value for parameter utb: UniqueTB[shapeless.::[TB,shapeless.::[TB,shapeless.HNil]]] UniqueTB[TB :: TB :: HNil] ^ 的操作,但是如果你不需要它,你可以不用方法保留它。