2

我有一个项目严重依赖其算法的确切蓝图,因为它经常变化。它处理事物的列表,并且这些事物与它们相关联的“事实”。我想使用 HList 来跟踪这些事实。这是我拥有的工作设置(scala 2.11,shapeless 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, ...]定义具有这些类型的 HList ?T*

4

0 回答 0