我的项目很大程度上依赖于算法的确切蓝图,因为它经常发生变化。它处理一系列事物,并且这些事物与它们有关联的“事实”。我想使用HList来跟踪这些事实。这是我的工作设置(scala 2.11,无形2.3.0):
import shapeless.{HList, HNil}
trait Fact
case class Fact1(v: Double = 0.5) extends Fact
case class Fact2(v: Double = 0.6) extends Fact
case class Fact3(v: Double) extends Fact
trait Thing
case class A(x: String = "whoah") extends Thing
def fact1(t: Thing) = Fact1()
def fact2(t: Thing) = Fact2()
case class Container[T <: HList](things: List[(Thing, T)]) {
def addInfo[FactType <: Fact](f: Thing => FactType): Container[shapeless.::[FactType, T]] =
copy(things = things.map(t => (t._1, f(t._1) :: t._2)))
def compute[Info, FactType](f: (Thing, Info) => FactType)(t: T => Info): Container[shapeless.::[FactType, T]] = {
copy(things = things.map { case (thing, facts) =>
val info = t(facts)
(thing, f(thing, info) :: facts)
})
}
def compute1[Info, FactType](f: (Thing, T) => FactType): Container[shapeless.::[FactType, T]] = {
copy(things = things.map { case (thing, facts) =>
(thing, f(thing, facts) :: facts)
})
}
}
def computer(t: Thing, info: (Fact1, Fact2)) = Fact3(info._1.v + info._2.v)
// This obviously doesn't work
/*def computerNotWorking[Facts <: HList](t: Thing, facts: Facts)
(implicit hs1: Selector[Facts, Fact1],
hs2: Selector[Facts, Fact2) = {
Fact3(facts.select[Fact1].v + facts.select[Fact2].v)
}*/
val lt = List(A("1") -> HNil, A("2") -> HNil)
val clt = Container(lt)
clt.addInfo(fact1)
.addInfo(fact2)
.compute(computer _) {
facts => (facts.select[Fact1], facts.select[Fact2])
}
//.compute1(computerNotWorking _) // see above why it doesn't work
这就是问题所在。这样做的理由是我有很多小函数和对象,它们执行不同的计算部分,并且由于这个算法的性质(我们用它进行了很多实验),我想用最少的代码重新删除和重新排列这些东西。 -写作。我希望保持代码的这些部分只使用他们需要了解的具体事实而不了解其他任何事情 - 使测试更容易,并且每个位都有一个目的。
再次提出这样的问题:是否可以定义一个名为HListWith[T1, T2, ...]
的类型(最多为随机数类型参数),以任何顺序定义其中包含T*
类型的HList?