アルゴリズムは頻繁に変更されるため、アルゴリズムの正確な設計図に大きく依存しているプロジェクトがあります。物事のリストを扱い、それらの物事には「事実」が関連付けられています。これらの事実を追跡するために 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
それが問題です。その正当な理由は、計算のさまざまな部分を実行する多くの小さな関数とオブジェクトがあり、このアルゴリズムの性質上 (私たちはそれを使って多くのことを実験しています)、最小限のコードでそれらを削除して再配置したいと考えています。 -書き込み。そして、コードのこれらの部分は、他のことは何も知らずに、知っておく必要のある特定の事実だけで動作するようにしたいと考えています。これにより、テストが容易になり、各ビットに 1 つの目的が与えられます。
繰り返しになりますが、これらの型を任意の順序でHListWith[T1, T2, ...]
含む HList を定義する (型引数の乱数まで) という型を定義することは可能ですか?T*