Scala 异构映射,编译时的依赖类型
试图使用Miles Sabin的技巧创建一个只接受一组预定义的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:
类型的参数的函数
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我觉得隐式很好。