感谢
https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0,我理解如何压缩无形的HLists:
从Shapeless 2.0.0-M1导入一些东西:
import shapeless._ import shapeless.ops.hlist._ import Syntax.std.tuple._ import Zipper._
创建两个HLists:
scala> val h1 = 5 :: "a" :: HNil h1: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: a :: HNil scala> val h2 = 6 :: "b" :: HNil h2: shapeless.::[Int,shapeless.HNil]] = 6 :: b :: HNil
拉链他们:
scala> (h1,h2).zip res52: ((Int,Int),(String,String)) = ((5,6),(a,b))
scala> def f[HL <: HList](h1: HL,h2: HL) = (h1,h2).zip f: [HL <: shapeless.HList](h1: HL,h2: HL)Unit
推断的返回类型是Unit,实际上将f应用于h1和h2就是这样:
scala> f(h1,h2) scala>
有没有办法定义f,以便在这种情况下得到((5,b))?
最终我要做的是定义一个拉伸两个HList然后映射它们的函数,选择基于抛硬币的_1或_2,这将产生另一个HL.
object mix extends poly1 { implicit def caseTuple[T] = at[(T,T)](t => if (util.Random.nextBoolean) t._2 else t._1) }
哪个在REPL中工作正常:
scala> (h1,h2).zip.map(mix) res2: (Int,String) = (5,b)
谢谢!
解决方法
您可以使用Zip(或在本例中为Zip.Aux)类型类在一个方法中包装所有内容:
import shapeless._,shapeless.ops.hlist._ object mix extends poly1 { implicit def caseTuple[T] = at[(T,T)](t => if (util.Random.nextBoolean) t._2 else t._1) } def zipAndMix[L <: HList,Z <: HList](h1: L,h2: L)(implicit zipper: Zip.Aux[L :: L :: HNil,Z],mapper: Mapper[mix.type,Z] ) = (h1 zip h2) map mix
现在假设您在问题中定义了h1和h2,您可以这样写:
scala> zipAndMix(h1,h2) res0: shapeless.::[Int,shapeless.HNil]] = 5 :: b :: HNil scala> zipAndMix(h1,h2) res1: shapeless.::[Int,shapeless.HNil]] = 6 :: a :: HNil scala> zipAndMix(h1,h2) res2: shapeless.::[Int,shapeless.HNil]] = 5 :: a :: HNil
等等.这将适用于2.0.0-M1或最新快照,尽管(正如我在上面的评论中所述),您可能会在this bug was fixed之前的路上遇到混乱的问题.