Question

Say that I have a trait Show[T] such as the one in Scalaz: https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Show.scala#L9

I also have a Shapeless HList that may look like "1" :: 2 :: 3L :: HNil.

Is there a way to find the Show instance for each element and apply shows such that I end up with "1" :: "2" :: "3L" :: HNil?

If any element were of a type that did not have an implicit Show instance in scope I would want a compile error.

I think that if I build up an HList of the Show instances I should be able to use zipApply to get the HList I want, but I don't know if there is a way to get have Scala infer the HList of Show instances instead of me building it up by hand.

Was it helpful?

Solution

If your goal is to apply the Show instances and you don't otherwise care about building up an HList of them, the easiest approach is probably to use a polymorphic function:

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

You could get an HList of the instances by changing the Poly1 a bit:

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

In some cases it can be useful to define your own type class to collect evidence that you've got certain type class instances:

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
}

But usually mapping with a polymorphic function that requires the instances will work just fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top