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

Scala 异构映射,编译时的依赖类型,scala,shapeless,Scala,Shapeless,试图使用Miles Sabin的技巧创建一个只接受一组预定义的类型的参数的函数 val bool = Boolean val timestamp = new Timestamp(date.getTime()) val str = "My String" 然后在编译时应该通过以下步骤 takeValue(bool) takeValue(timestamp) takeValue(str) could not find implicit value for parameter conv:

试图使用Miles Sabin的技巧创建一个只接受一组预定义的
类型的参数的函数

val bool =  Boolean
val timestamp = new Timestamp(date.getTime())
val str = "My String"
然后在编译时应该通过以下步骤

takeValue(bool)
takeValue(timestamp)
takeValue(str)
 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.
但是

其中,
takeValue
对于
takeValue(someIntValue)
应该失败,如果未定义
类型
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)
在编译时失败,因为没有为它定义任何合适的
隐式
。基本上想限制(在编译时)类型的
类型
takeValue
可以为其他类型接受并失败

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

takeValue("string")
它在编译时抛出以下命令

takeValue(bool)
takeValue(timestamp)
takeValue(str)
 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.

.type
的含义经常被误解。类型
值。类型
是一个只有一个值的类型-
。即使已知
字符串
值.类型
不是
字符串
,但具体来说只有一个
字符串
-

因此,代码尝试查找一个不存在的
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 }
如果
value.type
T
的子类型,则允许使用
MyConv[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
}

在这种情况下,我可能会避免使用方差,但除此之外,+1。@wingedsubmariner:回答得很好。这难道不是隐式的吗隐式val strConv=iMakeConv[Any,String]((x:Any)=>x.toString)`?@VikasPandya我觉得隐式很好。