Scala 在HList上映射一个属特征的子类

Scala 在HList上映射一个属特征的子类,scala,shapeless,Scala,Shapeless,我想把一个poly1函数映射到一个不成形的HList上。它的元素是参数化特征的子类。但是,我得到错误“找不到映射器的隐式值”。以下是一个基本示例: 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: Bi

我想把一个poly1函数映射到一个不成形的HList上。它的元素是参数化特征的子类。但是,我得到错误“找不到映射器的隐式值”。以下是一个基本示例:

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)}

}
运行此代码会产生
错误:(21,27)找不到参数m:shapeless.ops.hlist.Mapper.Aux[pour.type,Proc.I,Proc.Req]的隐式值。

虽然这看起来像一个简单的问题,但我还没有在其他答案中找到(或认识到)解决方案。我目前的解决方法是在
poly
中为
饮料的每个子类定义一个case。这显然不适用于该特征的许多子类。
有没有更好的解决方案(可能是使用TypeTags)

更新

对于任何(合理的)
Poly1
函数,该问题的一般答案由@Jasper_M给出。(该问题在中进一步概括。)对于上述示例中的特定转换
I=>Req
,可以使用更简单的解决方案

import syntax.std.tuple._
import poly._

def makeTwo(): Req =  (drinks.tupled flatMap identity).productElements

它给出了
10::15.0::1.0::HNil
。(请注意,
productElements
在Intellij 2017.2.6中被错误地标记为错误。此外,“非耦合”版本
会导致“隐式未找到”错误。)

尝试使用多态方法:

object pour extends Poly1{
  implicit def caseInt[A <: Drink[Int]] =
    at[A](o => o.v)
  implicit def caseDec[A <: Drink[BigDecimal]] =
    at[A](o => o.v)
}
对象1{
隐式def caseInt[A o.v]
隐式def caseDec[A o.v]
}

您提供的代码在2.12和2.11版本上都可以编译。@您说得对。调用
Proc.make()
没有说明这个问题。实际上
make
不是泛型的,所以
隐式m
是非常多余的,但这不是重点。@Jasper-m谢谢你的回答!如果每个元素都在另一个容器中,类似的东西会起作用吗?例如,有case类Box[+E](elem:E)和I=Box[Water]::…;Req=Box[Int]…;drinks=Box[Water(10)]…(如果有必要,我可以编辑这个问题或问另一个问题。)我会说:试试看,让我知道:-p但我认为它应该有效。