【问题标题】:Statically-typed heterogeneous list builder静态类型的异构列表构建器
【发布时间】:2014-10-07 10:07:41
【问题描述】:

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

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

理想情况下,我想在 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
    )
  )
)

通过在FieldType 类型中使用addValue 方法,编译器可以识别任意深度的参数类型:

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 的下一个参数的类型信息通过tail 成员包含在FieldValue 中,如V。但我无法找到一种方法让 addValue 方法可以使用这些信息,让编译器验证参数值的类型,并让 IDE 建议正确的类型。

【问题讨论】:

标签: scala types type-inference type-parameter heterogeneous


【解决方案1】:

您可能想看看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
                          ^

我不知道这是否已经满足你的需求,但无论如何你一定要检查 shapeless 的所有特性,因为它为这种泛型编程提供了许多便利

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-22
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多