我正在尝试以类型安全的方式进行这项工作:
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 分钟手动完成(或使用小脚本)。