我使用无形HMap
作为案例类的底层结构,充当共享同一父级的其他对象的聚合器。父特征允许访问名为arity
的Int值属性。我想在scanLeft
上使用HMap
来计算arity
中对象的累积HList
。我成功编写了Poly
个对象,允许使用arity
计算所有foldLeft
的总和,但在尝试将相同的概念应用于scanLeft
时,它不会再努力了。
问题1:有人看到我应该如何修改pointAccumulate
以支持scanLeft
操作吗?我希望lookup
类似Nat(2) :: Nat(5) :: Nat(8) :: HNil
(使用下面的示例)。
Q2:之后我将使用lookup
来搜索已知组合结构中累积arity的元素的索引。鉴于此,是否可以使用HList,或者我应该确保将lookup
作为List [Int]?
import shapeless._
import ops.hlist.{At, LeftFolder, LeftScanner}
object Point { type Point = (Double, Double) }
import Point._
sealed trait Shape {
val arity: Int
}
case class Line(p0: Point, p1: Point) extends Shape {
val arity = 2
}
case class Triangle(p0: Point, p1: Point, p2: Point) extends Shape {
val arity = 3
}
case class Canvas[L <: HList](shapes: L)
(implicit
val ev: LUBConstraint[L, Shape],
val lf: LeftFolder.Aux[L, Int, pointAccumulate.type, Int],
val ls: LeftScanner[L, Int, pointAccumulate.type]) {
lazy val parameterCount: Int = shapes.foldLeft(0)(pointAccumulate)
lazy val lookup = shapes.scanLeft(0)(pointAccumulate)
}
object pointCount extends Poly1 {
implicit def default[T <: Shape] = at[T](_.arity)
}
object pointAccumulate extends Poly2 {
implicit def default[T <: Shape](implicit pt: pointCount.Case.Aux[T, Int]) =
at[Int, T] { (i, p) => i + pointCount(p) }
}
object App {
def main(args: Array[String]): Unit = {
val l0 = Line((-2, 2), (2, -2))
val tr1 = Triangle((0,0), (0, 1), (1, 0))
val tr2 = Triangle((1,1), (1, 2), (2, 1))
val c = Canvas(l0 :: tr1 :: tr2 :: HNil)
println(c.lookup)
}
}
答案 0 :(得分:0)
我设法使用@devkat中的提示解决了这个问题。这是代码的工作
import shapeless._
import ops.hlist.{At, LeftFolder, LeftScanner}
object Point { type Point = (Double, Double) }
import Point._
sealed trait Shape {
val arity: Int
}
case class Line(p0: Point, p1: Point) extends Shape {
val arity = 2
}
case class Triangle(p0: Point, p1: Point, p2: Point) extends Shape {
val arity = 3
}
case class Canvas[L <: HList, LL <: HList](shapes: L)
(implicit
val ev: LUBConstraint[L, Shape],
val lf: LeftFolder.Aux[L, Int, pointAccumulate.type, Int],
val ls: LeftScanner.Aux[L, Int, pointAccumulate.type, LL],
val ev2: LUBConstraint[LL, Int]) {
lazy val parameterCount: Int = shapes.foldLeft(0)(pointAccumulate)
lazy val lookup = shapes.scanLeft(0)(pointAccumulate)
}
object pointCount extends Poly1 {
implicit def default[T <: Shape] = at[T](_.arity)
}
object pointAccumulate extends Poly2 {
implicit def default1[T <: Shape](implicit pt: pointCount.Case.Aux[T, Int]) =
at[T, Int] { (p, i) => i + pointCount(p) }
implicit def default2[T <: Shape](implicit pt: pointCount.Case.Aux[T, Int]) =
at[Int, T] { (i, p) => i + pointCount(p) }
}
object App2 {
def main(args: Array[String]): Unit = {
val l0 = Line((-2, 2), (2, -2))
val tr1 = Triangle((0,0), (0, 1), (1, 0))
val tr2 = Triangle((1,1), (1, 2), (2, 1))
val c = Canvas(l0 :: tr1 :: tr2 :: HNil)
println(c.parameterCount)
println(c.lookup)
}
}