scala – 如何使用一元类型构造函数推断Shapeless记录值的内部类
发布时间:2020-12-16 09:55:50 所属栏目:安全 来源:网络整理
导读:我无法理解Shapeless记录选择器与 scala类型推断交互的方式.我正在尝试创建一个方法,可以通过键从Shapeless记录中获取字段,只有当字段的值具有某个一元类型构造函数时,在这种特殊情况下Vector [_],然后获取内部值推断出Vector中的V型,在本例中是Vector.apply
我无法理解Shapeless记录选择器与
scala类型推断交互的方式.我正在尝试创建一个方法,可以通过键从Shapeless记录中获取字段,只有当字段的值具有某个一元类型构造函数时,在这种特殊情况下Vector [_],然后获取内部值推断出Vector中的V型,在本例中是Vector.apply().
我觉得我很亲密.这是有效的,具有Int的具体内部类型: val record = ( "a" ->> Vector(0,2,4) ) :: ( "b" ->> Set(1,3,5) ) :: HNil def getIntFromVectorField[L <: HList](l: L,fieldName:Witness,index:Int)(implicit sel: Selector.Aux[L,fieldName.T,Vector[Int]] ):Int = l(fieldName).apply(index) getIntFromVectorField(record,"a",1) // Returns 1 getIntFromVectorField(record,"b",0) // Does not compile,as intended 但如果我试图推断内部类型,它会失败: def getValueFromVectorField[L <: HList,V](l:L,Vector[V]] ):V = l(fieldName).apply(index) // Compiles getValueFromVectorField(record,1) // Why does this not compile? 这是完整的错误: could not find implicit value for parameter sel: shapeless.ops.record.Selector[shapeless.::[scala.collection.immutable.Vector[Int] with shapeless.labelled.KeyTag[String("a"),scala.collection.immutable.Vector[Int]],shapeless.::[scala.collection.immutable.Set[Int] with shapeless.labelled.KeyTag[String("b"),scala.collection.immutable.Set[Int]],shapeless.HNil]],String("a")]{type Out = scala.collection.immutable.Vector[V]} 我能做的是这样的: def getValueFromVectorField[L <: HList,T,T],unpack: Unpack1[T,Vector,V] ):V = l(fieldName) match { case v:Vector[V] => v.apply(index) } getValueFromVectorField(record,1) // Returns 1,Yay! getValueFromVectorField(record,as intended 哪个应该是安全的,是吗?但模式匹配对于无形而言并不是非常惯用,我想知道为什么更简洁的推理方法不起作用.有更清洁的方法吗? 解决方法
在这样的情况下,Scala对于类型推断非常糟糕(你想要统一函数依赖的结果和类似Vector [V]并且推断出V).
您可以通过分解步骤来帮助编译器完成整个过程: import shapeless._,ops.record.Selector,syntax.singleton._ def getValueFromVectorField[L <: HList,VS,V]( l: L,fieldName: Witness,index: Int )(implicit sel: Selector.Aux[L,VS],ev: VS <:< Vector[V] ): V = sel(l).apply(index) val record = ( "a" ->> Vector(0,5) ) :: HNil getValueFromVectorField(record,as intended 现在它首先推断VS,然后弄清楚VS是Vector [V]的子类型,而不是一步完成两者. 这与你的Unpack1版本完全相同,只是Unpack1只证明T是Vector [V] – 它实际上并没有给你一个从T得到Vector [V]的方法(不像<:< ;,哪个). 所以你的Unpack1版本是安全的,因为你可以说服自己它提供了你需要的所有证据,但它们不是编译器理解的形式,所以你必须使用模式中的类型情况进行向下转换比赛. <:其中更好,因为编译器确实理解它,但也因为它更容易被识别为此限制的解决方法,因为它是由标准库提供的,等等. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |