I have an implicit helper set up like this:
trait Helper[T] {
def help(entry: T): Unit
}
object Helpers {
implicit object XHelper extends Helper[X] {
override def help(entry: X): Unit = {println("x")}
}
implicit object YHelper extends Helper[Y] {
override def help(entry: Y): Unit = {println("y")}
}
def help[T](entry: T)(implicit helper: Helper[T]): Unit = {
helper.help(entry)
}
}
I would like to set up a collection of elements and run help
on each of them. However, the following gives a compiler error because we can't guarantee all elements have matching Helper
s:
val data = Seq[_](new X(), new Y())
data.foreach(entry => Helpers.help(entry))
If we had a generic type T
we could enforce the implicit constraint on it with [T: Helper]
, but that doesn't work on _
. How can I enforce that each element of data
has a matching Helper
?
It's not possible with type like Seq
since it is only parametrized for one element type that is common for all its elements.
However, you can achieve this with Shapeless HLists and polymorphics functions (Poly):
class X
class Y
trait Helper[T] {
def help(entry: T): Unit
}
object Helpers {
implicit object XHelper extends Helper[X] {
override def help(entry: X): Unit = println("x")
}
implicit object YHelper extends Helper[Y] {
override def help(entry: Y): Unit = println("y")
}
}
import shapeless._
object helper extends Poly1 {
implicit def tCase[T: Helper]: Case.Aux[T, Unit] =
at(implicitly[Helper[T]].help(_))
}
val hlist = new X :: new Y :: HNil
hlist.map(helper)
// Output:
x
y