【发布时间】:2018-01-08 23:48:31
【问题描述】:
假设HList 的元素是通用特征的子类。每个元素都包含在case class Box[E](elem E) 中。 Box 在E 中是不变的,这会导致将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]
case class Box[E](elem: E) // NB! invariance in E
object pour extends Poly1{
implicit def caseInt[A <: Box[Drink[Int]]] = at[A](o => Box(o.elem.v * 2))
implicit def caseDec[A <: Box[Drink[BigDecimal]]] = at[A](o => Box(o.elem.v + 5.0))
}
object Proc {
type I = Box[Water] :: Box[Squash] :: Box[Juice] :: HNil
type O = Box[Int] :: Box[BigDecimal] :: Box[BigDecimal] :: HNil
val drinks: I = Box(Water(10)) :: Box(Squash(15.0)) :: Box(Juice(2.0)) :: HNil
def make()(implicit m: ops.hlist.Mapper.Aux[pour.type, I, O]): O = drinks.map(pour)
}
object Main extends App{
override def main(args: Array[String]): Unit = Proc.make()
}
*函数pour 将@Jasper_M 的答案应用于Mapping over HList with subclasses of a generic trait。
这段代码导致
Error:(38, 22) could not find implicit value for parameter m: shapeless.ops.hlist.Mapper.Aux[pour.type,Proc.I,Proc.O]
Proc.make()。
此外,过滤Proc.drinks.covariantFilter[Box[Drink[Int]]] 会产生HNil。 (此过滤器实现了@Travis Brown 对Do a covariant filter on an HList 的回答。)
在我的项目中无法定义解决问题的Box[+E]。一个幼稚的解决方案——在pour 中为Drink 的每个子类提供一个案例——无法扩展。 (这可以通过将单态函数传递给pour 来实现,我不知道怎么做。)
在此设置中是否有更明智的方法来映射或过滤 HList?
【问题讨论】: