查找Shapeless HList的类型类实例

时间:2014-03-08 12:28:09

标签: scala shapeless hlist

假设我有一个特征Show[T],例如Scalaz中的特征:https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Show.scala#L9

我还有一个可能看起来像HList的无形"1" :: 2 :: 3L :: HNil

有没有办法找到每个元素的Show个实例并应用shows,以便最终得到"1" :: "2" :: "3L" :: HNil

如果任何元素的类型在作用域中没有隐式Show实例,我会想要编译错误。

我认为,如果我构建HListShow个实例,我应该可以使用zipApply来获取我想要的HList,但我不知道知道是否有办法让Scala推断HListShow实例,而不是我手工构建它。

1 个答案:

答案 0 :(得分:8)

如果您的目标是应用Show个实例,而您又不关心构建HList个实例,那么最简单的方法可能就是使用多态函数:

import scalaz._, Scalaz._, shapeless._

val xs = "1" :: 2 :: 3L :: HNil

object show extends Poly1 {
  implicit def forShowable[A: Show] = at[A](_.shows)
}

val strings: String :: String :: String :: HNil = xs map show

您可以通过更改HList来获得Poly1个实例:

object showInstance extends Poly1 {
  implicit def forShowable[A: Show] = at[A](_ => Show[A])
}

在某些情况下,定义您自己的类型类以收集您已获得某些类型类实例的证据会很有用:

trait AllShowable[L <: HList, S <: HList] {
  def instances: S
}

implicit object hnilAllShowable extends AllShowable[HNil, HNil] {
  def instances = HNil
}

implicit def hlistAllShowable[H: Show, TL <: HList, TS <: HList](
  implicit ts: AllShowable[TL, TS]
) = new AllShowable[H :: TL, Show[H] :: TS] {
  def instances = Show[H] :: ts.instances
}

但通常使用需要实例的多态函数进行映射才能正常工作。