I'm trying to map a poly1 function over a shapeless HList. Its elements are subclasses of a parameterised trait. However, I get the error "couldn't find implicit value for the Mapper". Here's a basic example:
import shapeless._
trait Drink[+A]{
def v: A
}
case class Water(v: Int) extends Drink[Int]
case class Juice(v: BigDecimal) extends Drink[BigDecimal]
case class Squash(v: BigDecimal) extends Drink[BigDecimal]
object pour extends Poly1{
implicit def caseInt: Case.Aux[Drink[Int], Int] =
at(o => o.v)
implicit def caseDec: Case.Aux[Drink[BigDecimal], BigDecimal] =
at(o => o.v)
}
object Proc {
type I = Water ::Squash ::Juice :: HNil
type Req = Int ::BigDecimal ::BigDecimal :: HNil
val drinks: I = Water(10)::Squash(15.0):: Juice(1.0)::HNil
def make()(implicit m: ops.hlist.Mapper.Aux[pour.type, I, Req]): Req = { drinks.map(pour)}
}
Running this code produces
Error:(21, 27) could not find implicit value for parameter m: shapeless.ops.hlist.Mapper.Aux[pour.type,Proc.I,Proc.Req]
Although this appears like a simple problem, I haven't found (or recognised) a solution in other answers. My current workaround is to define a case, in poly
, for each subclass of Drink
. This is obviously not appropriate with many subclasses of the trait.
Could there be a better solution (perhaps with TypeTags)?
UPDATE
A general answer to this question, for any (reasonable) Poly1
function, is given by @Jasper_M. (The question is further generalised in Using shapeless HLists with invariant containers.) For the specific transformation I => Req
in the above example a simpler solution is
import syntax.std.tuple._
import poly._
def makeTwo(): Req = (drinks.tupled flatMap identity).productElements
which gives 10 :: 15.0 :: 1.0 :: HNil
. (Note that productElements
is wrongly flagged as error in Intellij 2017.2.6. Moreover, the "untupled" version drinks flatMap identity
causes an "implicit not found" error.)
Proc.make()
is missing to illustrate the problem. – Jasper-Mmake
is not generic soimplicit m
is pretty redundant, but that's beside the point here. – Jasper-M