a clean way to combine two tuples into a new larger tuple in scala?

jxstanford picture jxstanford · Jan 27, 2012 · Viewed 12.7k times · Source

Let's say I have the following tuples:

scala> val t1 = Tuple2("abcd", "efg")
t1: (java.lang.String, java.lang.String) = (abcd,efg)

scala> val t2 = Tuple2(1234, "lmnop")
t2: (Int, java.lang.String) = (1234,lmnop)

scala> val t3 = Tuple3("qrs", "tuv", "wxyz")
t3: (java.lang.String, java.lang.String, java.lang.String) = (qrs,tuv,wxyz)

Is there a friendly way to combine them (in two steps if necessary) into a Tuple7? I'm really looking for a general answer for combining tuples of arbitrary size, and realize that there will be limitations due to the capped maximum tuple size. I am specifically looking for a tuple result, not a collection.

Answer

huynhjl picture huynhjl · Jan 27, 2012

Shapeless requires dependent method types (-Ydependent-method-types) and I wish there was a downloadable binary for 2.9.1 so that I can simply try it out but it's really seems elegant. Based on this unit test it would apply to your case like this:

import shapeless.Tuples._
import shapeless.HList._
val t7 = (t1.hlisted ::: t2.hlisted ::: t3.hlisted).tupled

Although Miles indicates there is not guarantee of support, it actually has unit tests and the source is on github with an open source license so at least it's not just an experiment in a blog post.

Edit: works as advertized - took some time to compile and I had to add -Xss1m to sbt:

$ scala -Ydependent-method-types -cp target/scala-2.9.1/shapeless_2.9.1-1.1.0.jar
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import shapeless.Tuples._
import shapeless.Tuples._

scala> import shapeless.HList._
import shapeless.HList._

scala> val t1 = Tuple2("abcd", "efg")
t1: (java.lang.String, java.lang.String) = (abcd,efg)

scala> val t2 = Tuple2(1234, "lmnop")
t2: (Int, java.lang.String) = (1234,lmnop)

scala> val t3 = Tuple3("qrs", "tuv", "wxyz")
t3: (java.lang.String, java.lang.String, java.lang.String) = (qrs,tuv,wxyz)

scala> (t1.hlisted ::: t2.hlisted ::: t3.hlisted).tupled
res0: (java.lang.String, java.lang.String, Int, java.lang.String, java.lang.String,
java.lang.String, java.lang.String) = (abcd,efg,1234,lmnop,qrs,tuv,wxyz)