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

Vik*_*dya 3 scala shapeless

试图通过Miles Sabin 使用这个技巧来创建一个只接受一组预定义参数的函数types.

val bool =  Boolean
val timestamp = new Timestamp(date.getTime())
val str = "My String"
Run Code Online (Sandbox Code Playgroud)

然后跟随应该在编译时通过

takeValue(bool)
takeValue(timestamp)
takeValue(str)
Run Code Online (Sandbox Code Playgroud)

但

这里takeValue应该失败takeValue(someIntValue),如果implicit用于type Int不defined.And这种故障会在编译的时候.

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

然后

implicit val strAny = iMakeConv((x:Any) => x.toString)
Run Code Online (Sandbox Code Playgroud)

然后我想takeValue(str)在编译时工作,但在编译时takeValue(someIntValue)失败,因为没有任何适当的implicit定义.基本上想要限制(在编译时)类型types takeValue可以接受和失败的其他人.

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

takeValue("string")
Run Code Online (Sandbox Code Playgroud)

它在编译时抛出

 could not find implicit value for parameter conv: 
 MyConv[String("string")]
- not enough arguments for method takeValue: (implicit conv: 
 MyConv[String("string")])scalaz.\/[Throwable,conv.V]. 
 Unspecified value parameter conv.
Run Code Online (Sandbox Code Playgroud)

win*_*ner 5

意思.type经常被误解.类型value.type是只有一个值的类型 - value.即使value已知String,value.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))
Run Code Online (Sandbox Code Playgroud)

或者,也可以制作MyConv 逆变的类型参数:

trait MyConv[-K] { type V; def convert: AnyRef => V }
Run Code Online (Sandbox Code Playgroud)

MyConv[T]如果value.type是子类型,则允许使用a T.

您还需要一个不同的MyConv和iMakeConv:

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