8

假设我有一个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实例,我会想要一个编译错误。

我认为如果我构建一个HList实例,Show我应该能够使用它zipApply来获得HList我想要的,但我不知道是否有办法让 Scala 推断HList实例Show而不是我手动构建它.

4

1 回答 1

9

如果您的目标是应用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
}

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

于 2014-03-08T13:08:20.023 回答