静态类型的异构列表构建器

Lui*_*gro 2 types scala type-inference heterogeneous type-parameter

我想要实现的是一种方法:

  1. 定义异构列表的类型列表
  2. 从上面的定义,构建一个静态类型的值列表

理想情况下,我想在IDE中键入以下表达式:

val record = types.addValue("test").addValue(123).addValue(new java.util.Date())
Run Code Online (Sandbox Code Playgroud)

具有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)
Run Code Online (Sandbox Code Playgroud)

这是一个由以下内容组成的记录的示例规范String, Int, Date:

val types = FieldType(
  classOf[String], FieldType(
    classOf[Int], FieldType(
      classOf[java.util.Date], emptyFieldType
    )
  )
)
Run Code Online (Sandbox Code Playgroud)

通过使用类型中的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
Run Code Online (Sandbox Code Playgroud)

但....

我还没有找到一种方法来实现FieldValue类型的转发方法,以实现一个流畅的界面,如我的第一个例子:

val record = types.addValue("test").addValue(123).addValue(new java.util.Date())
Run Code Online (Sandbox Code Playgroud)

这是一个伪代码来表达这个想法:

case class FieldValue[V, T <: FieldType[_, _]](value: V, tail: T) {
  def addValue(x: What Here??) = tail.addValue(x) // not compiling!
}
Run Code Online (Sandbox Code Playgroud)

我想,那一定是有可能的,因为对于下一参数的类型信息addValue包含在FieldValue通过tail成员,V.但我找不到一种方法可以使该信息可用于该addValue方法,让编译器验证参数值的类型,以及IDE以建议正确的类型.

Gab*_*lla 5

你可能想看看无形.

这是一个简单的示例,演示如何静态指定异构列表的类型:

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
                          ^
Run Code Online (Sandbox Code Playgroud)

我不知道这是否已经满足您的需求,但无论如何您一定要检查无形的所有功能,因为它为这种通用编程提供了许多功能