假设我有一个特征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
实例,而不是我手工构建它。
答案 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
}
但通常使用需要实例的多态函数进行映射才能正常工作。