The supposed type of function that zip HLists

Thanks https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0 I understand how to button shapeless HLists:

Import some stuff from Shapeless 2.0.0-M1:

import shapeless._ import shapeless.ops.hlist._ import syntax.std.tuple._ import Zipper._ 

Create two 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.::[String,shapeless.HNil]] = 6 :: b :: HNil 

Pin them:

 scala> (h1, h2).zip res52: ((Int, Int), (String, String)) = ((5,6),(a,b)) 

Now try defining a function that does the same:

 scala> def f[HL <: HList](h1: HL, h2: HL) = (h1, h2).zip f: [HL <: shapeless.HList](h1: HL, h2: HL)Unit 

The inferred return type is Unit, and indeed, applying f to h1 and h2 does just that:

 scala> f(h1, h2) scala> 

Is there a way to determine f so that in this case I get ((5,6), (a, b))?

Ultimately, what I'm trying to do is define a function that fastens two HLists and then displays them, choosing either _1 or _2, based on a coin toss, which will give another HL.

 object mix extends Poly1 { implicit def caseTuple[T] = at[(T, T)](t => if (util.Random.nextBoolean) t._2 else t._1) } 

What works great in REPL:

 scala> (h1, h2).zip.map(mix) res2: (Int, String) = (5,b) 

But I will try to solve this problem when I try to use it in a function.

Thanks!

+3
source share
2 answers

You can wrap everything in one method using the Zip class (or in this case 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 

Suppose you have h1 and h2 defined as in the question, you can write this:

 scala> zipAndMix(h1, h2) res0: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: b :: HNil scala> zipAndMix(h1, h2) res1: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 6 :: a :: HNil scala> zipAndMix(h1, h2) res2: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: a :: HNil 

And so on. This will work either in version 2.0.0-M1, or in the last snapshot, although (as I noted in the comment above) you may encounter confusing problems along the way until this error was fixed .

+6
source

Given a compiler error, and some view tests in hlist.scala, zip is defined as follows:

 def f[L <: HList, OutT <: HList](l : L)( implicit transposer : Transposer.Aux[L, OutT], mapper : Mapper[tupled.type, OutT]) = l.transpose.map(tupled) 

And my mix application can be defined as follows:

 def g[L <: HList](l : L)( implicit mapper: Mapper[mix.type,L]) = l.map(mix) 

Composition does what I was looking for:

 scala> g(f(h1 :: h2 :: HNil)) res12: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: b :: HNil scala> g(f(h1 :: h2 :: HNil)) res13: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 6 :: a :: HNil scala> g(f(h1 :: h2 :: HNil)) res14: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 6 :: b :: HNil 
+2
source

All Articles