Frank
Frank

Reputation: 4461

Scala: Convert heterogeneous Tuple to List

On the Scala command line, there is no problem writing:

List((1,2),(1,'a'))

But I can't seem to write a function that would convert a Tuple2 to a List, because Tuple2 takes 2 type parameters, but List only one. Any attempt such as:

def tuple2ToList[T1, T2](pair: (T1, T2)): List[Any] = List(pair._1, pair._2)

seems to be bound to lose type information. Is there anything we can do to preserve some type information in the process?

Upvotes: 0

Views: 126

Answers (1)

Andrey Tyukin
Andrey Tyukin

Reputation: 44908

This is a solution proposed by @BenReich in a comment

Simply use one type parameter instead of two, the compiler will automatically select the least upper bound of the types of the two tuple elements:

def tupleToList[T](p: (T, T)): List[T] = List(p._1, p._2)

Examples:

scala> tupleToList((Some(42), None))
res4: List[Option[Int]] = List(Some(42), None)

scala> tupleToList((0.9999, 1))
res5: List[AnyVal] = List(0.9999, 1)

scala> tupleToList((Set(1), List(1)))
res6: List[scala.collection.immutable.Iterable[Int] with Int => AnyVal] = List(Set(1), List(1))

This is the old suboptimal solution, I'll leave it here as context for @BenReich's comment.

Define the return type as the least upper bound of T1 and T2:

def tupleToListRescueTypeInfo[R, T1 <: R, T2 <: R](p: (T1, T2)): List[R] = 
  List(p._1, p._2)

Little test:

scala> tupleToListRescueTypeInfo((2, 3))
res0: List[Int] = List(2, 3)

scala> tupleToListRescueTypeInfo((Some[Int](3), None))
res1: List[Option[Int]] = List(Some(3), None)

scala> tupleToListRescueTypeInfo((List(1,2), Set(1,2)))
res2: List[scala.collection.immutable.Iterable[Int] with Int => AnyVal] = 
  List(List(1, 2), Set(1, 2))

It obviously cannot preserve all type information, but it at least attempts to rescue as much as possible.

Upvotes: 2

Related Questions