键入无形HList内容的推断

时间:2014-02-17 10:41:57

标签: scala shapeless hlist

此示例已简化。

我有一组这样的课程:

case class KeyMapping[KeyType](k:KeyType)

class WrappedMapping[KeyType](m:T forSome {type T <: KeyMapping[KeyType]}) {
  val k:KeyType = ???
}

在以下代码中,正确推断出类型:

 val w = new WrappedMapping(KeyMapping("key"))

 //The statement below gives the correct error
 //type mismatch; 
 //  found : w.k.type (with underlying type String)  required: Nothing
 //val test1:Nothing = w.k

我不知道如何正确推断以下类型:

class Mappings[KeyType, L <: HList](mappings:L) {
  val k:KeyType = ???
}

val m = new Mappings(KeyMapping("key1") :: KeyMapping("key2") :: HNil)

// should not compile, k should be of type String
val test2:Nothing = m.k

我是否可以根据KeyType的内容推断HList

1 个答案:

答案 0 :(得分:8)

Shapeless提供了一个隐含的ToList,毫不奇怪,它将HLists转换为Lists。

为了做到这一点,它必须首先计算HList中类型的LUB(最小上限),这是你可以使用的东西:

import shapeless.ops.hlist.ToList

class Mappings[L <: HList, Lub](mappings:L)(implicit toList: ToList[L, Lub]) {
  ...
}

L进入后,隐式解决方案会发现一个(且唯一的)有效ToList实例受L约束,Lub类型被拉出。< / p>

这还不够,因为Lub将是KeyMapping[String],而您想要的只是String部分。像往常一样,无形,解决方案是添加另一个隐含的:

class Mappings[L <: HList, Lub, KeyType](mappings:L)(
  implicit
  val toList: ToList[L, Lub],
  val kt: Lub <:< KeyMapping[KeyType]
) {
  val k: KeyType = null.asInstanceOf[KeyType]
}

(隐含不需要是val s,但如果你在REPL中探索事物时它会有所帮助)

这断言,Lub对应于KeyMapping[KeyType] 类型(例如,它是一个子类型或完全相同的类型),其中KeyType是,然而,未知。同样,指定的约束只有一个有效的解决方案,而KeyType参数被拉出为String

我不知道您计划如何实施k,但您可能会发现拥有toList实例可以帮助您这样做,因为它允许您现在调用mappings.toList < / p>