異種のリストである必要がある可変オブジェクトに要素を追加することは可能ですか?
つまり、私はダイクストラのアルゴリズムを扱っており、そのような方法でグラフの弧にいくつかの関数を保持する必要があります:
class Arc[M, N, T, K](var start: Node[M], var end: Node[N], var f: T => K)
start
- は開始ノードです。end
- 終了ノード; f
- はノード間の何らかの機能であり、アークはこの機能を維持するためのオブジェクトであり、私にとって最も重要なことです。
すべて完璧ですが、ノード内のリストにすべてのアークを保持します。
class Node[T] (s: T) (implicit m: TypeTag[T]) {
var transitions: List[Arc[T, _, _, _]] = Nil
//...
def addArc[M, N, L] (end: Node[M], f: N => L): Arc[T, _, _, _] = {
transitions = new Arc(this, end, f) :: transitions
transitions.head
}
}
おわかりのように、問題は、単純なリストでは型が失われることです。ノードに新しいアークを追加すると、タイプに関するすべての情報が失われます。
問題を解決する可能な方法は、次を使用することHLists
です。いくつかの作業コードの例(説明にさらに情報を追加するため):
// for example we got some type convertion functions
def doubleToInt(x: Double) = x.toInt
def doubleToString(x: Double) = x.toString
def stringToInt(x: String) = x.toInt
def intToDouble(x: Int) = x.toDouble
// and we got some class, with two any args and one function;
class testyfunc[M, N, K, T] (a: M, b: N, c: K => T) {
var f: K => T = c(_)
}
// ok lets build HList
var omglist = HNil
var omglist1 = (new testyfunc (1, "234", intToDouble)) :: omglist
var omglist2 = (new testyfunc (1, "234", doubleToInt)) :: omglist1
var omglist3 = (new testyfunc (1, "234", doubleToString)) :: omglist2
var omglist4 = (new testyfunc (1, "234", stringToInt)) :: omglist3
// it all works!
println(omglist4.head.f("223")) // > 223
// lest check types; yeah it's perfect!
/* shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,String,Int],
shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,Double,java.lang.String],
shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,Double,Int],
shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,Int,Double],
shapeless.HNil]]]] */
ちなみに、今はすべてそのような方法です:
var omglistNH: List[testyfunc[_, _, _, _]] = Nil // here we loose types!
omglistNH = (new testyfunc (1, "234", intToDouble)) :: omglistNH
omglistNH = (new testyfunc (1, "234", doubleToInt)) :: omglistNH
omglistNH = (new testyfunc (1, "234", doubleToString)) :: omglistNH
omglistNH = (new testyfunc (1, "234", stringToInt)) :: omglistNH
println(omglistNH.head.f("223"))
// obviously we got a type error; cause of incorrect types
/* type mismatch;
found : String("223")
required: _$9 where type _$9
println(omglistNH.head.f("223"))
^ */
問題は、以下のコードのように (正しくない -- タイプ エラー)、この HList に要素を追加するにはどうすればよいかということです。
var omglist = HNil
omglist = (new testyfunc (1, "234", intToDouble)) :: omglist
omglist = (new testyfunc (1, "234", doubleToInt)) :: omglist
omglist = (new testyfunc (1, "234", doubleToString)) :: omglist
omglist = (new testyfunc (1, "234", stringToInt)) :: omglist
このタイプの不一致を渡す方法さえわからなかったので、すべての遷移をノードのフィールドとして保持し、すべてのタイプを保持する方法がわかりません。
編集
うーん、トランジションをコンストラクターに渡すことができ、可変オブジェクトをまったく使用しません。