异构映射,编译时的依赖类型

时间:2014-06-27 04:37:46

标签: scala shapeless

尝试使用Miles Sabin的this技巧来创建一个只接受一组预定义types参数的函数。

val bool =  Boolean
val timestamp = new Timestamp(date.getTime())
val str = "My String"

然后跟随应该在编译时传递

takeValue(bool)
takeValue(timestamp)
takeValue(str)

但是

如果takeValue takeValue(someIntValue)的{​​{1}}未定义,则implicit type的{​​{1}}将失败。此失败将在编译时发生。

Int

然后

trait MyConv[K] { type V; def convert: AnyRef => V }

def iMakeConv[V0](con: AnyRef => V0) = new MyConv[con.type] {
  override type V = V0
  val convert = con
}

  def takeValue(value:AnyRef)(implicit conv :MyConv[value.type]) : \/[Throwable,conv.V] = \/.fromTryCatch(conv.convert(value))

然后我希望implicit val strAny = iMakeConv((x:Any) => x.toString) 在编译时工作但takeValue(str)在编译时失败,因为没有为它定义任何适当的takeValue(someIntValue)。基本上希望限制(在编译时)implicit types的类型可以为其他人带来和失败。

当然,我在这里做错了,因为在打电话时

takeValue

它在编译时抛出

takeValue("string")

1 个答案:

答案 0 :(得分:5)

.type的含义经常被误解。类型value.type是一种只有一个值的类型 - value。即使知道valueStringvalue.type也不是String,但只有一个String - value

因此,即使有MyConv[value.type]可用,代码也会尝试查找MyConv[String],但都不存在。

takeValue使用类型参数:

def takeValue[T](value: T)(implicit conv: MyConv[T]) : \/[Throwable, conv.V] = \/.fromTryCatch(conv.convert(value))

或者选择MyConv逆变的类型参数:

trait MyConv[-K] { type V; def convert: AnyRef => V }

如果MyConv[T]value.type的子类型,则可以使用T

您还需要一个不同的MyConviMakeConv

trait MyConv[K] { type V; def convert: K => V }

def iMakeConv[K, V0](con: K => V0) = new MyConv[K] {
  override type V = V0
  val convert = con
}