我想要实现的目标是:
理想情况下,我想在IDE中键入以下表达式:
val record = types.addValue("test").addValue(123).addValue(new java.util.Date())
将addValue()
的参数类型限制为IDE类型推理引擎。
以下是第1点的工作实现:记录字段类型的规范:
case class FieldType[V, T <: FieldType[_, _]](clazz: Class[V], tail: T) {
def addValue(value: V) = FieldValue(value, tail)
}
case class FieldValue[V, T <: FieldType[_, _]](value: V, tail: T)
object emptyFieldType extends FieldType(classOf[Null], null)
这是由String, Int, Date
:
val types = FieldType(
classOf[String], FieldType(
classOf[Int], FieldType(
classOf[java.util.Date], emptyFieldType
)
)
)
通过使用addValue
类型中的FieldType
方法,编译器可以识别任何深度的参数类型:
val a = types.addValue("") // here only String allowed
val b = types.tail.addValue(23) // here only Int allowed
val c = types.tail.tail.addValue(new java.util.Date()) // here only Date allowed
可是...
我还没有找到一种方法在FieldValue
类型上实现转发方法,以实现一个流畅的界面,如我的第一个例子:
val record = types.addValue("test").addValue(123).addValue(new java.util.Date())
这是一个伪代码:
case class FieldValue[V, T <: FieldType[_, _]](value: V, tail: T) {
def addValue(x: What Here??) = tail.addValue(x) // not compiling!
}
我认为必须有可能,因为addValue
的下一个参数的类型信息通过FieldValue
成员tail
包含在V
中。但我找不到一种方法可以使这些信息可用于addValue
方法,让编译器验证参数值的类型,以及IDE来建议正确的类型。
答案 0 :(得分:5)
您可能需要查看shapeless。
这是一个简单的例子,演示了如何静态指定异构列表的类型:
type R = String :: Int :: java.util.Date :: HNil
val record: R = "test" :: 123 :: new java.util.Date() :: HNil
// record: R = test :: 123 :: Thu Aug 14 00:21:52 CEST 2014 :: HNil
val record: R = "test" :: "foo" :: new java.util.Date() :: HNil
// error: type mismatch;
found : shapeless.::[String,shapeless.::[String,shapeless.::[java.util.Date,shapeless.HNil]]]
required: R
(which expands to) shapeless.::[String,shapeless.::[Int,shapeless.::[java.util.Date,shapeless.HNil]]]
val record: R = "test" :: "hola" :: new java.util.Date() :: HNil
^
我不知道这是否已经满足您的需求,但无论如何您一定要检查无形的所有功能,因为它为这种通用编程提供了许多功能