私はこれをタイプセーフな方法で機能させようとしています:
val rows = db.select( ID_COLUMN, STR("name"), INT("count") ). from("tablename") ......
for ( (id, name, count) <- rows ) {
//some code to use the individual values
}
これまでのところ、シェイプレス以外にこれをタイプセーフにする別の方法は見つかりませんでした。
私は slick やその他の ORM について知っています。
HList は、異種のオブジェクトの束を渡し、特定の型の値のリストを取得する方法のようです。
私はこのようなことをしようとしました:
trait ColDef [X] {
def colName
def valalue (m:Map[String, Object]):X
}
object XS extends ColDef[String]{
def colName = "s"
def value (m:Map[String, Object]) = m("s").asInstanceOf[String]
}
object XI extends ColDef[Integer]{
def colName = "i"
def value (m:Map[String, Object]) = m("i").asInstanceOf[Integer]
}
val xhl = XS::XI::HNil
val data:Map[String,Object] = Map(("s" ->"asdf"), ("i" -> new Integer(5)))
object p1 extends Poly1 {
implicit def getValue[T, S <% ColDef[T]] = at[S] (coldef => coldef.value(data) )
}
val res = xhl map p1
val (s, i) = res.tupled //this works, giving s:String, and i:Integer
//but following does not compile
def nextstep(hl : HList, data:Map[String,Object]) = {
hl map p1
}
重要なことを繰り返します。
HList/Shapeless は問題を解決するための候補となる可能性がありますが、この演習の目標ではありません。私の目標は、関数の戻り値の型を、渡された変数の型とパラメーターの数に対応させることです。
私の小さなユーティリティのユーザーが HList について知る必要がなければ理想的ですが、それは実際の要件ではありません。
重要な部分は、結果のタイプを params のタイプと一致させることです。
val param1 = new Conf[String]
val param2 = new Conf[Integer]
... etc ....
val res = function(param1, param2, param3)
より正確には、上記のパラメータのペイロード タイプです。つまり、 res のタイプは T(String, Integer, ....) になります。
別の説明を追加させてください。任意のアリティのメソッドを作成し、パラメーターの数ごとに関数を作成することを避けたいと考えています。22 個のメソッドで問題がなければ、次のようになります。
def f[A](a:ColDef[A]):(A)
def f[A,B](a:ColDef[A], b:ColDef[B]):(A,B)
def f[A,B,C](a:ColDef[A], b:ColDef[B],c:ColDef[C]):(A,B,C)
..... and so on
そして、可能なすべてのタプルが明示的に定義されるため、 shapeless または HList は必要ありません。
これら 3 つの署名を実際に見てみましょう - それらを 22 にするのは少し時間がかかりますが、形のない依存関係を回避し、実装もワンライナーになります。30 分かけて手動で (または小さなスクリプトを使用して) 実行する必要があるかもしれません。