ネストしたTupleで遊ぶ

# <i class="fa fa-pencil-square-o"></i> ネストしたタプルをひたすらフラットなタプルにする
きっともっとうまいやり方あるんだろうなー(/ω・＼)ﾁﾗｯ

```scala
object TupleImplicits {                                                         //defined module TupleImplicits
                                                                                //
  object tuple2Flat {                                                           //
    def apply[A, B, C](x: Tuple2[A, Tuple2[B, C]]) = {                          //
      (x._1, x._2._1, x._2._2)                                                  //
    }                                                                           //
    def apply[A, B, C, D](x: Tuple2[A, Tuple2[B, Tuple2[C, D]]]) = {            //
      (x._1, x._2._1, x._2._2._1, x._2._2._2)                                   //
    }                                                                           //
    def apply[A, B, C, D, E](x: Tuple2[A, Tuple2[B, Tuple2[C, Tuple2[D, E]]]]) =//
      (x._1, x._2._1, x._2._2._1, x._2._2._2._1, x._2._2._2._2)                 //
    }                                                                           //
    def apply[A, B, C, D, E, F](x: Tuple2[A, Tuple2[B, Tuple2[C, Tuple2[D, Tuple//
      (x._1, x._2._1, x._2._2._1, x._2._2._2._1, x._2._2._2._2._1, x._2._2._2._2//
    }                                                                           //
  }                                                                             //
                                                                                //
  object tuple3Flat {                                                           //
    def apply[A, B, C, D](x: Tuple2[A, Tuple3[B, C, D]]) = {                    //
      (x._1, x._2._1, x._2._2, x._2._3)                                         //
    }                                                                           //
  }                                                                             //
                                                                                //
  object tuple4Flat {                                                           //
    def apply[A, B, C, D, E](x: Tuple2[A, Tuple4[B, C, D, E]]) = {              //
      (x._1, x._2._1, x._2._2, x._2._3, x._2._4)                                //
    }                                                                           //
  }                                                                             //
                                                                                //
  implicit class UnTuple[A](t: A) {                                             //
    def shift[B](a: B) = (t, a)                                                 //
    def shift[B, C](a: Tuple2[B, C]) = tuple2Flat(t, a)                         //
    def shift[B, C, D](a: Tuple2[B, Tuple2[C, D]]) = tuple2Flat(t, a)           //
    def shift[B, C, D, E](a: Tuple2[B, Tuple2[C, Tuple2[D, E]]]) = tuple2Flat(t,//
    def shift[B, C, D](a: Tuple3[B, C, D]) = tuple3Flat(t, a)                   //
    def shift[B, C, D, E](a: Tuple4[B, C, D, E]) = tuple4Flat(t, a)             //
  }                                                                             //
}                                                                               //
                                                                                //
import TupleImplicits._                                                         //import TupleImplicits._
                                                                                //
// tuple2 flat                                                                  //
tuple2Flat(1, (2, 3))                                                           //res0: (Int, Int, Int) = (1,2,3)
tuple2Flat(1, (2, (3, 4)))                                                      //res1: (Int, Int, Int, Int) = (1,2,3,4)
tuple2Flat(1, (2, (3, (4, 5))))                                                 //res2: (Int, Int, Int, Int, Int) = (1,2,3,4,5)
                                                                                //
// tuple3 flat                                                                  //
tuple3Flat(1, (2, 3, 4))                                                        //res3: (Int, Int, Int, Int) = (1,2,3,4)
                                                                                //
// tuple4 flat                                                                  //
tuple4Flat(1, (2, 3, 4, 5))                                                     //res4: (Int, Int, Int, Int, Int) = (1,2,3,4,5)
                                                                                //
// shift                                                                        //
1 shift "スフィア"                                                                  //res5: (Int, String) = (1,スフィア)
1 shift ("スフィア", "乃木坂46")                                                       //res6: (Int, String, String) = (1,スフィア,乃木坂46)
(1 shift ("バナナマン" shift (3.0 shift 4L)))                                        //res7: (Int, String, Double, Long) = (1,バナナマン,3.0,4)
                                                                                //
                                                                   //
```

# <i class="fa fa-fire"></i> で、
なにがしたかったんだったか忘れた

# shapless
コメントで頂いたのを使ってみた

```scala
import shapeless._                                                              //import shapeless._
import ops.tuple.FlatMapper                                                     //import shapeless.ops.tuple.FlatMapper
import syntax.std.tuple._                                                       //import shapeless.syntax.std.tuple._
import test._                                                                   //import shapeless.test._
                                                                                //
trait LowPriorityFlatten extends Poly1 {                                        //defined trait LowPriorityFlatten
  implicit def default[T] = at[T](Tuple1(_))                                    //
}                                                                               //
object flatten extends LowPriorityFlatten {                                     //defined module flatten
  implicit def caseTuple[P <: Product](implicit fm: FlatMapper[P, flatten.type])//
    at[P](_.flatMap(flatten))                                                   //
}                                                                               //
                                                                                //
val t1 = (1, ((2, 3), 4))                                                       //t1: (Int, ((Int, Int), Int)) = (1,((2,3),4))
val f1 = flatten(t1)                                                            //f1: (Int, Int, Int, Int) = (1,2,3,4)
val t2 = (1, (2, (3, 4)))                                                       //t2: (Int, (Int, (Int, Int))) = (1,(2,(3,4)))
flatten(t2)                                                                     //res0: (Int, Int, Int, Int) = (1,2,3,4)
val t3 = ((1, 2), 3)                                                            //t3: ((Int, Int), Int) = ((1,2),3)
flatten(t3)                                                                     //res1: (Int, Int, Int) = (1,2,3)
val t4 = (((((5, (4, (1, 2))), 3))))                                            //t4: ((Int, (Int, (Int, Int))), Int) = ((5,(4,(1,2))),3)
val f4 = flatten(t4)                                                            //f4: (Int, Int, Int, Int, Int) = (5,4,1,2,3)
                                                                                //
f4.getClass                                                                     //res2: Class[?0] = class scala.Tuple5
                                                                                //
```

すげぇ・・・