My objective is to flatten a `Tuple`

and get its flattened version with the exact tyoe.

So the following should compie:

```
val c1: Tuple4[Int, Int, Char, Char] = flatten( ((1,2), ('a', 'b')) )
```

I cannot get the types correct. I seem to only get the top type `Tuple`

.

So I experimented with `concat`

to check the typing. The following work correctly:

```
def concat[T1 <: Tuple, T2 <: Tuple](t1: T1, t2: T2): Tuple.Concat[T1, T2] = {
t1 ++ t2
}
def concat2[S1 <: Tuple, S2 <: Tuple, T1 <: Tuple, T2 <: Tuple](s1: S1, s2: S2, t1: T1, t2: T2):
Tuple.Concat[Tuple.Concat[S1, S2], Tuple.Concat[T1, T2]] = {
val u1 = concat(s1, s2)
val u2 = concat(t1, t2)
u1 ++ u2
}
def concat2a[S1 <: Tuple, S2 <: Tuple, T1 <: Tuple, T2 <: Tuple](s1: S1, s2: S2, t1: T1, t2: T2):
Tuple.Concat[Tuple.Concat[S1, S2], Tuple.Concat[T1, T2]] = {
val u1:Tuple.Concat[S1, S2] = concat(s1, s2)
val u2:Tuple.Concat[T1, T2] = concat(t1, t2)
u1 ++ u2
}
```

So on further investigation I tried this:

```
def split[S1 <: Tuple, S2 <: Tuple, O <: Tuple](o: O): (S1, S2) = {
o match {
case (s@(h1 *: t2 *: _)) *: t =>
println(s"s = $s")
println(s"t = $t")
(s, t)
}
}
```

```
[error] | ^
[error] | Found: (s : Any *: Tuple)
[error] | Required: S1
[error] |
[error] | where: S1 is a type in method split with bounds <: Tuple
[error] -- [E007] Type Mismatch Error: /home/hmf/Test.scala:126:12
[error] 126 | (s, t)
[error] | ^
[error] | Found: (t : Tuple)
[error] | Required: S2
[error] |
[error] | where: S2 is a type in method split with bounds <: Tuple
```

One of the issues I see is that the tuple is constructed with a head and tail, and this head need not be a tuple - hence the `Any`

(if this is not so please correct me).

Another issue is that when I pattern match I get *general* Tuple which does not match a specific `<: Tuple`

.

So my question is, is their any way I can match and retain the most specific type information?

TIA