Scala, generic tuple












12















I have a generic method that can accept any tuple of any size, the only constraint is that the first element of this tuple should be of type MyClass.



Something like this:



trait MyTrait[T <: (MyClass, _*)] {
getMyClass(x: T): MyClass = x._1
}


I've tried this



trait MyTrait[T <: (MyClass, _) with (MyClass, _, _) with (MyClass, _, _) with ...] {
getMyClass(x: T): MyClass = x._1
}


but I get the error unboud wildcard type










share|improve this question



























    12















    I have a generic method that can accept any tuple of any size, the only constraint is that the first element of this tuple should be of type MyClass.



    Something like this:



    trait MyTrait[T <: (MyClass, _*)] {
    getMyClass(x: T): MyClass = x._1
    }


    I've tried this



    trait MyTrait[T <: (MyClass, _) with (MyClass, _, _) with (MyClass, _, _) with ...] {
    getMyClass(x: T): MyClass = x._1
    }


    but I get the error unboud wildcard type










    share|improve this question

























      12












      12








      12


      1






      I have a generic method that can accept any tuple of any size, the only constraint is that the first element of this tuple should be of type MyClass.



      Something like this:



      trait MyTrait[T <: (MyClass, _*)] {
      getMyClass(x: T): MyClass = x._1
      }


      I've tried this



      trait MyTrait[T <: (MyClass, _) with (MyClass, _, _) with (MyClass, _, _) with ...] {
      getMyClass(x: T): MyClass = x._1
      }


      but I get the error unboud wildcard type










      share|improve this question














      I have a generic method that can accept any tuple of any size, the only constraint is that the first element of this tuple should be of type MyClass.



      Something like this:



      trait MyTrait[T <: (MyClass, _*)] {
      getMyClass(x: T): MyClass = x._1
      }


      I've tried this



      trait MyTrait[T <: (MyClass, _) with (MyClass, _, _) with (MyClass, _, _) with ...] {
      getMyClass(x: T): MyClass = x._1
      }


      but I get the error unboud wildcard type







      scala generics






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 12 '18 at 9:18









      GigitsuGigitsu

      300112




      300112
























          6 Answers
          6






          active

          oldest

          votes


















          4














          It's a little bit unsafe but you can use Structural type in this case:



          trait MyTrait {
          def getMyClass(x: {def _1: MyClass}): MyClass = x._1
          }





          share|improve this answer





















          • 2





            This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

            – Tim
            Dec 12 '18 at 10:25













          • @Tim, yes thank you I mean structural type.

            – mkUltra
            Dec 12 '18 at 10:31






          • 1





            This was surprisingly simple.

            – Sarvesh Kumar Singh
            Dec 12 '18 at 14:15











          • Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

            – Yuriy
            Dec 13 '18 at 1:30











          • This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

            – Gigitsu
            Dec 13 '18 at 13:07



















          11














          If you want to do this without either boilerplate or runtime reflection, Shapeless is your best bet. You can use the IsComposite type class to put type-level constraints on the first element of a tuple:



          import shapeless.ops.tuple.IsComposite

          trait MustBeFirst

          class MyClass[P <: Product](p: P)(implicit ev: IsComposite[P] { type H = MustBeFirst }) {
          def getMustBeFirst(x: P): MustBeFirst = ev.head(p)
          }


          And then:



          scala> val good2 = (new MustBeFirst {}, "")
          good2: (MustBeFirst, String) = ($anon$1@7294acee,"")

          scala> val good3 = (new MustBeFirst {}, "", 123)
          good3: (MustBeFirst, String, Int) = ($anon$1@6eff9288,"",123)

          scala> val good4 = (new MustBeFirst {}, "", 'xyz, 123)
          good4: (MustBeFirst, String, Symbol, Int) = ($anon$1@108cdf99,"",'xyz,123)

          scala> val bad2 = ("abc", 123)
          bad2: (String, Int) = (abc,123)

          scala> new MyClass(good2)
          res0: MyClass[(MustBeFirst, String)] = MyClass@5297aa76

          scala> new MyClass(good3)
          res1: MyClass[(MustBeFirst, String, Int)] = MyClass@3f501844

          scala> new MyClass(good4)
          res2: MyClass[(MustBeFirst, String, Symbol, Int)] = MyClass@24e15478

          scala> new MyClass(bad2)
          <console>:15: error: could not find implicit value for parameter ev: shapeless.ops.tuple.IsComposite[(String, Int)]{type H = MustBeFirst}
          new MyClass(bad2)
          ^


          If you need to use a trait, you can put the ev (for "evidence") requirement inside the definition instead of in the constructor:



          trait MyTrait[P <: Product] {
          implicit def ev: IsComposite[P] { type H = MustBeFirst }
          }


          Now any class instantiating MyTrait will have to provide evidence that P is a tuple with MustBeFirst as its first element.






          share|improve this answer


























          • Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

            – C4stor
            Dec 12 '18 at 10:46











          • @C4stor Good point—I'll update the answer to clarify asap.

            – Travis Brown
            Dec 12 '18 at 11:19






          • 1





            @C4stor IsComposite works for Tuple1, with tail type being Unit.

            – Oleg Pyzhcov
            Dec 12 '18 at 12:19











          • Oh, interesting ! Shapeless is tricky :D

            – C4stor
            Dec 12 '18 at 13:18






          • 1





            Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

            – Gigitsu
            Dec 13 '18 at 13:02





















          2














          Scala can't use generic tuple with unknown size because Products don's inherit themeselfs. You can try to use Shapeless or Products from play json lib.






          share|improve this answer



















          • 1





            Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

            – Travis Brown
            Dec 12 '18 at 10:28











          • Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

            – C4stor
            Dec 12 '18 at 10:49



















          0














          You need to inherit your trait from Product, through which you can have productIterator, productArity and, productElement to handle the returned value. Here is an example



          case class MyClass()

          trait MyTrait[T <: Product] {
          def getMyClass(x: T): Option[MyClass] =
          if(
          x.productIterator.hasNext
          &&
          x.productIterator.next().isInstanceOf[MyClass]
          ){
          Some(x.productIterator.next().asInstanceOf[MyClass])
          } else {
          None
          }
          }

          case class Test() extends MyTrait[Product]


          And you can invoke like this



          Test().getMyClass((MyClass(), 1,3,4,5))
          //res1: Option[MyClass] = Some(MyClass())

          Test().getMyClass((1,3,4,5))
          //res2: Option[MyClass] = None


          Hope this helps you.






          share|improve this answer

































            -1














            As others said you can use shapeless:



            import shapeless.ops.tuple.IsComposite
            import shapeless.syntax.std.tuple._

            class MyClass(i : Int){
            def hello() = println(i)
            }


            object Tup extends App {

            def getMyClass[P <: Product](p: P)(implicit ev: IsComposite[P]): MyClass = {
            if (p.head.isInstanceOf[MyClass]) p.head.asInstanceOf[MyClass] else throw new Exception()
            }
            val x= (new MyClass(1),5,6)
            val y = (new MyClass(2),7)

            val c = getMyClass(x)
            val c1 = getMyClass(y)
            c.hello()
            c1.hello()

            val c2 = getMyClass((1,5,6,7)) // exception
            c2.hello()

            }





            share|improve this answer
























            • This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

              – Travis Brown
              Dec 12 '18 at 11:34











            • @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

              – Arnon Rotem-Gal-Oz
              Dec 12 '18 at 12:34











            • Why all the casting, then?

              – Travis Brown
              Dec 12 '18 at 12:38











            • @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

              – Arnon Rotem-Gal-Oz
              Dec 12 '18 at 13:19



















            -1














            If you are looking for compile time guarantee then this is one of the use cases for
            Shapeless,



            You need to add Shapeless in your build.sbt,



            libraryDependencies ++= Seq("
            com.chuusai" %% "shapeless" % "2.3.3"
            )


            Now, you can use Shapeless to define a typesafe getter which comes with compile time guarantees,



            scala> import shapeless._
            // import shapeless._

            scala> import ops.tuple.IsComposite
            // import ops.tuple.IsComposite

            scala> import syntax.std.tuple._
            // import syntax.std.tuple._

            scala> case class Omg(omg: String)
            // defined class Omg

            scala> val myStringTuple = ("All is well", 42, "hope")
            // myStringTuple: (String, Int, String) = (All is well,42,hope)

            scala> val myOmgTuple = (Omg("All is well"), 42, "hope")
            // myOmgTuple: (Omg, Int, String) = (Omg(All is well),42,hope)


            Now if you want to enrich your tuples with a "first" getter with a specific type then,



            scala> implicit class GetterForProduct[B <: Product](b: B) {
            | def getFirst[A](implicit comp: IsComposite[B] { type H = A }): A = b.head
            | }
            // defined class GetterForProduct

            scala> val myString = myStringTuple.getFirst[String]
            // myString: String = All is well

            scala> val myOmgError = myOmgTuple.getFirst[String]
            // <console>:24: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
            // val myOmgError = myOmgTuple.getFirst[String]
            // ^

            scala> val myOmg = myOmgTuple.getFirst[Omg]
            // myOmg: Omg = Omg(All is well


            If you don't need the implicit enrichment and are just looking for a way to "lock" the type in a getter and use it for corresponding types,



            scala> trait FirstGetterInProduct[A] {
            | def getFirst[B <: Product](b: B)(implicit comp: IsComposite[B] { type H = A }): A = b.head
            | }
            // defined trait FirstGetterInProduct

            scala> object firstGetterInProductForString extends FirstGetterInProduct[String]
            // defined object firstGetterInProductForString

            scala> object firstGetterInProductForOmg extends FirstGetterInProduct[Omg]
            // defined object firstGetterInProductForOmg

            // Right tuple with right getter,
            scala> val myString = firstGetterInProductForString.getFirst(myStringTuple)
            // myString: String = All is well

            // will fail at compile time for tuple with different type for first
            scala> val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
            // <console>:23: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
            // val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
            // ^

            scala> val myOmg = firstGetterInProductForOmg.getFirst(myOmgTuple)
            // myOmg: Omg = Omg(All is well)





            share|improve this answer


























            • What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

              – jwvh
              Dec 12 '18 at 11:52











            • @jwvh You are right. Fixed.

              – Sarvesh Kumar Singh
              Dec 12 '18 at 14:08











            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53739656%2fscala-generic-tuple%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            6 Answers
            6






            active

            oldest

            votes








            6 Answers
            6






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            4














            It's a little bit unsafe but you can use Structural type in this case:



            trait MyTrait {
            def getMyClass(x: {def _1: MyClass}): MyClass = x._1
            }





            share|improve this answer





















            • 2





              This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

              – Tim
              Dec 12 '18 at 10:25













            • @Tim, yes thank you I mean structural type.

              – mkUltra
              Dec 12 '18 at 10:31






            • 1





              This was surprisingly simple.

              – Sarvesh Kumar Singh
              Dec 12 '18 at 14:15











            • Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

              – Yuriy
              Dec 13 '18 at 1:30











            • This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

              – Gigitsu
              Dec 13 '18 at 13:07
















            4














            It's a little bit unsafe but you can use Structural type in this case:



            trait MyTrait {
            def getMyClass(x: {def _1: MyClass}): MyClass = x._1
            }





            share|improve this answer





















            • 2





              This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

              – Tim
              Dec 12 '18 at 10:25













            • @Tim, yes thank you I mean structural type.

              – mkUltra
              Dec 12 '18 at 10:31






            • 1





              This was surprisingly simple.

              – Sarvesh Kumar Singh
              Dec 12 '18 at 14:15











            • Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

              – Yuriy
              Dec 13 '18 at 1:30











            • This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

              – Gigitsu
              Dec 13 '18 at 13:07














            4












            4








            4







            It's a little bit unsafe but you can use Structural type in this case:



            trait MyTrait {
            def getMyClass(x: {def _1: MyClass}): MyClass = x._1
            }





            share|improve this answer















            It's a little bit unsafe but you can use Structural type in this case:



            trait MyTrait {
            def getMyClass(x: {def _1: MyClass}): MyClass = x._1
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 12 '18 at 10:31

























            answered Dec 12 '18 at 10:09









            mkUltramkUltra

            733922




            733922








            • 2





              This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

              – Tim
              Dec 12 '18 at 10:25













            • @Tim, yes thank you I mean structural type.

              – mkUltra
              Dec 12 '18 at 10:31






            • 1





              This was surprisingly simple.

              – Sarvesh Kumar Singh
              Dec 12 '18 at 14:15











            • Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

              – Yuriy
              Dec 13 '18 at 1:30











            • This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

              – Gigitsu
              Dec 13 '18 at 13:07














            • 2





              This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

              – Tim
              Dec 12 '18 at 10:25













            • @Tim, yes thank you I mean structural type.

              – mkUltra
              Dec 12 '18 at 10:31






            • 1





              This was surprisingly simple.

              – Sarvesh Kumar Singh
              Dec 12 '18 at 14:15











            • Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

              – Yuriy
              Dec 13 '18 at 1:30











            • This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

              – Gigitsu
              Dec 13 '18 at 13:07








            2




            2





            This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

            – Tim
            Dec 12 '18 at 10:25







            This is compound type or "structural type" which, unlike "Duck typing", has a clearly-defined meaning is Scala.

            – Tim
            Dec 12 '18 at 10:25















            @Tim, yes thank you I mean structural type.

            – mkUltra
            Dec 12 '18 at 10:31





            @Tim, yes thank you I mean structural type.

            – mkUltra
            Dec 12 '18 at 10:31




            1




            1





            This was surprisingly simple.

            – Sarvesh Kumar Singh
            Dec 12 '18 at 14:15





            This was surprisingly simple.

            – Sarvesh Kumar Singh
            Dec 12 '18 at 14:15













            Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

            – Yuriy
            Dec 13 '18 at 1:30





            Just to strength constrain you may use Product { def _1: MyClass }, but it steel can accept case class with def _1

            – Yuriy
            Dec 13 '18 at 1:30













            This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

            – Gigitsu
            Dec 13 '18 at 13:07





            This is very simple to use, thank you. Anyway I had to enable reflective call, am I right?

            – Gigitsu
            Dec 13 '18 at 13:07













            11














            If you want to do this without either boilerplate or runtime reflection, Shapeless is your best bet. You can use the IsComposite type class to put type-level constraints on the first element of a tuple:



            import shapeless.ops.tuple.IsComposite

            trait MustBeFirst

            class MyClass[P <: Product](p: P)(implicit ev: IsComposite[P] { type H = MustBeFirst }) {
            def getMustBeFirst(x: P): MustBeFirst = ev.head(p)
            }


            And then:



            scala> val good2 = (new MustBeFirst {}, "")
            good2: (MustBeFirst, String) = ($anon$1@7294acee,"")

            scala> val good3 = (new MustBeFirst {}, "", 123)
            good3: (MustBeFirst, String, Int) = ($anon$1@6eff9288,"",123)

            scala> val good4 = (new MustBeFirst {}, "", 'xyz, 123)
            good4: (MustBeFirst, String, Symbol, Int) = ($anon$1@108cdf99,"",'xyz,123)

            scala> val bad2 = ("abc", 123)
            bad2: (String, Int) = (abc,123)

            scala> new MyClass(good2)
            res0: MyClass[(MustBeFirst, String)] = MyClass@5297aa76

            scala> new MyClass(good3)
            res1: MyClass[(MustBeFirst, String, Int)] = MyClass@3f501844

            scala> new MyClass(good4)
            res2: MyClass[(MustBeFirst, String, Symbol, Int)] = MyClass@24e15478

            scala> new MyClass(bad2)
            <console>:15: error: could not find implicit value for parameter ev: shapeless.ops.tuple.IsComposite[(String, Int)]{type H = MustBeFirst}
            new MyClass(bad2)
            ^


            If you need to use a trait, you can put the ev (for "evidence") requirement inside the definition instead of in the constructor:



            trait MyTrait[P <: Product] {
            implicit def ev: IsComposite[P] { type H = MustBeFirst }
            }


            Now any class instantiating MyTrait will have to provide evidence that P is a tuple with MustBeFirst as its first element.






            share|improve this answer


























            • Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

              – C4stor
              Dec 12 '18 at 10:46











            • @C4stor Good point—I'll update the answer to clarify asap.

              – Travis Brown
              Dec 12 '18 at 11:19






            • 1





              @C4stor IsComposite works for Tuple1, with tail type being Unit.

              – Oleg Pyzhcov
              Dec 12 '18 at 12:19











            • Oh, interesting ! Shapeless is tricky :D

              – C4stor
              Dec 12 '18 at 13:18






            • 1





              Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

              – Gigitsu
              Dec 13 '18 at 13:02


















            11














            If you want to do this without either boilerplate or runtime reflection, Shapeless is your best bet. You can use the IsComposite type class to put type-level constraints on the first element of a tuple:



            import shapeless.ops.tuple.IsComposite

            trait MustBeFirst

            class MyClass[P <: Product](p: P)(implicit ev: IsComposite[P] { type H = MustBeFirst }) {
            def getMustBeFirst(x: P): MustBeFirst = ev.head(p)
            }


            And then:



            scala> val good2 = (new MustBeFirst {}, "")
            good2: (MustBeFirst, String) = ($anon$1@7294acee,"")

            scala> val good3 = (new MustBeFirst {}, "", 123)
            good3: (MustBeFirst, String, Int) = ($anon$1@6eff9288,"",123)

            scala> val good4 = (new MustBeFirst {}, "", 'xyz, 123)
            good4: (MustBeFirst, String, Symbol, Int) = ($anon$1@108cdf99,"",'xyz,123)

            scala> val bad2 = ("abc", 123)
            bad2: (String, Int) = (abc,123)

            scala> new MyClass(good2)
            res0: MyClass[(MustBeFirst, String)] = MyClass@5297aa76

            scala> new MyClass(good3)
            res1: MyClass[(MustBeFirst, String, Int)] = MyClass@3f501844

            scala> new MyClass(good4)
            res2: MyClass[(MustBeFirst, String, Symbol, Int)] = MyClass@24e15478

            scala> new MyClass(bad2)
            <console>:15: error: could not find implicit value for parameter ev: shapeless.ops.tuple.IsComposite[(String, Int)]{type H = MustBeFirst}
            new MyClass(bad2)
            ^


            If you need to use a trait, you can put the ev (for "evidence") requirement inside the definition instead of in the constructor:



            trait MyTrait[P <: Product] {
            implicit def ev: IsComposite[P] { type H = MustBeFirst }
            }


            Now any class instantiating MyTrait will have to provide evidence that P is a tuple with MustBeFirst as its first element.






            share|improve this answer


























            • Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

              – C4stor
              Dec 12 '18 at 10:46











            • @C4stor Good point—I'll update the answer to clarify asap.

              – Travis Brown
              Dec 12 '18 at 11:19






            • 1





              @C4stor IsComposite works for Tuple1, with tail type being Unit.

              – Oleg Pyzhcov
              Dec 12 '18 at 12:19











            • Oh, interesting ! Shapeless is tricky :D

              – C4stor
              Dec 12 '18 at 13:18






            • 1





              Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

              – Gigitsu
              Dec 13 '18 at 13:02
















            11












            11








            11







            If you want to do this without either boilerplate or runtime reflection, Shapeless is your best bet. You can use the IsComposite type class to put type-level constraints on the first element of a tuple:



            import shapeless.ops.tuple.IsComposite

            trait MustBeFirst

            class MyClass[P <: Product](p: P)(implicit ev: IsComposite[P] { type H = MustBeFirst }) {
            def getMustBeFirst(x: P): MustBeFirst = ev.head(p)
            }


            And then:



            scala> val good2 = (new MustBeFirst {}, "")
            good2: (MustBeFirst, String) = ($anon$1@7294acee,"")

            scala> val good3 = (new MustBeFirst {}, "", 123)
            good3: (MustBeFirst, String, Int) = ($anon$1@6eff9288,"",123)

            scala> val good4 = (new MustBeFirst {}, "", 'xyz, 123)
            good4: (MustBeFirst, String, Symbol, Int) = ($anon$1@108cdf99,"",'xyz,123)

            scala> val bad2 = ("abc", 123)
            bad2: (String, Int) = (abc,123)

            scala> new MyClass(good2)
            res0: MyClass[(MustBeFirst, String)] = MyClass@5297aa76

            scala> new MyClass(good3)
            res1: MyClass[(MustBeFirst, String, Int)] = MyClass@3f501844

            scala> new MyClass(good4)
            res2: MyClass[(MustBeFirst, String, Symbol, Int)] = MyClass@24e15478

            scala> new MyClass(bad2)
            <console>:15: error: could not find implicit value for parameter ev: shapeless.ops.tuple.IsComposite[(String, Int)]{type H = MustBeFirst}
            new MyClass(bad2)
            ^


            If you need to use a trait, you can put the ev (for "evidence") requirement inside the definition instead of in the constructor:



            trait MyTrait[P <: Product] {
            implicit def ev: IsComposite[P] { type H = MustBeFirst }
            }


            Now any class instantiating MyTrait will have to provide evidence that P is a tuple with MustBeFirst as its first element.






            share|improve this answer















            If you want to do this without either boilerplate or runtime reflection, Shapeless is your best bet. You can use the IsComposite type class to put type-level constraints on the first element of a tuple:



            import shapeless.ops.tuple.IsComposite

            trait MustBeFirst

            class MyClass[P <: Product](p: P)(implicit ev: IsComposite[P] { type H = MustBeFirst }) {
            def getMustBeFirst(x: P): MustBeFirst = ev.head(p)
            }


            And then:



            scala> val good2 = (new MustBeFirst {}, "")
            good2: (MustBeFirst, String) = ($anon$1@7294acee,"")

            scala> val good3 = (new MustBeFirst {}, "", 123)
            good3: (MustBeFirst, String, Int) = ($anon$1@6eff9288,"",123)

            scala> val good4 = (new MustBeFirst {}, "", 'xyz, 123)
            good4: (MustBeFirst, String, Symbol, Int) = ($anon$1@108cdf99,"",'xyz,123)

            scala> val bad2 = ("abc", 123)
            bad2: (String, Int) = (abc,123)

            scala> new MyClass(good2)
            res0: MyClass[(MustBeFirst, String)] = MyClass@5297aa76

            scala> new MyClass(good3)
            res1: MyClass[(MustBeFirst, String, Int)] = MyClass@3f501844

            scala> new MyClass(good4)
            res2: MyClass[(MustBeFirst, String, Symbol, Int)] = MyClass@24e15478

            scala> new MyClass(bad2)
            <console>:15: error: could not find implicit value for parameter ev: shapeless.ops.tuple.IsComposite[(String, Int)]{type H = MustBeFirst}
            new MyClass(bad2)
            ^


            If you need to use a trait, you can put the ev (for "evidence") requirement inside the definition instead of in the constructor:



            trait MyTrait[P <: Product] {
            implicit def ev: IsComposite[P] { type H = MustBeFirst }
            }


            Now any class instantiating MyTrait will have to provide evidence that P is a tuple with MustBeFirst as its first element.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 12 '18 at 12:38

























            answered Dec 12 '18 at 10:17









            Travis BrownTravis Brown

            115k9290549




            115k9290549













            • Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

              – C4stor
              Dec 12 '18 at 10:46











            • @C4stor Good point—I'll update the answer to clarify asap.

              – Travis Brown
              Dec 12 '18 at 11:19






            • 1





              @C4stor IsComposite works for Tuple1, with tail type being Unit.

              – Oleg Pyzhcov
              Dec 12 '18 at 12:19











            • Oh, interesting ! Shapeless is tricky :D

              – C4stor
              Dec 12 '18 at 13:18






            • 1





              Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

              – Gigitsu
              Dec 13 '18 at 13:02





















            • Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

              – C4stor
              Dec 12 '18 at 10:46











            • @C4stor Good point—I'll update the answer to clarify asap.

              – Travis Brown
              Dec 12 '18 at 11:19






            • 1





              @C4stor IsComposite works for Tuple1, with tail type being Unit.

              – Oleg Pyzhcov
              Dec 12 '18 at 12:19











            • Oh, interesting ! Shapeless is tricky :D

              – C4stor
              Dec 12 '18 at 13:18






            • 1





              Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

              – Gigitsu
              Dec 13 '18 at 13:02



















            Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

            – C4stor
            Dec 12 '18 at 10:46





            Probably nitpicking, but I if read shapeless source correctly, IsComposite will also witness that the tuple is of size at least 2. It may be a relevant detail for the asker since tuples of size 1, however awkward, are a thing ^^

            – C4stor
            Dec 12 '18 at 10:46













            @C4stor Good point—I'll update the answer to clarify asap.

            – Travis Brown
            Dec 12 '18 at 11:19





            @C4stor Good point—I'll update the answer to clarify asap.

            – Travis Brown
            Dec 12 '18 at 11:19




            1




            1





            @C4stor IsComposite works for Tuple1, with tail type being Unit.

            – Oleg Pyzhcov
            Dec 12 '18 at 12:19





            @C4stor IsComposite works for Tuple1, with tail type being Unit.

            – Oleg Pyzhcov
            Dec 12 '18 at 12:19













            Oh, interesting ! Shapeless is tricky :D

            – C4stor
            Dec 12 '18 at 13:18





            Oh, interesting ! Shapeless is tricky :D

            – C4stor
            Dec 12 '18 at 13:18




            1




            1





            Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

            – Gigitsu
            Dec 13 '18 at 13:02







            Altought I like this solution and shapeless in general, I don't know how to use this in my case. This is my actual use case: pastebin.com/yCKs0eiQ

            – Gigitsu
            Dec 13 '18 at 13:02













            2














            Scala can't use generic tuple with unknown size because Products don's inherit themeselfs. You can try to use Shapeless or Products from play json lib.






            share|improve this answer



















            • 1





              Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

              – Travis Brown
              Dec 12 '18 at 10:28











            • Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

              – C4stor
              Dec 12 '18 at 10:49
















            2














            Scala can't use generic tuple with unknown size because Products don's inherit themeselfs. You can try to use Shapeless or Products from play json lib.






            share|improve this answer



















            • 1





              Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

              – Travis Brown
              Dec 12 '18 at 10:28











            • Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

              – C4stor
              Dec 12 '18 at 10:49














            2












            2








            2







            Scala can't use generic tuple with unknown size because Products don's inherit themeselfs. You can try to use Shapeless or Products from play json lib.






            share|improve this answer













            Scala can't use generic tuple with unknown size because Products don's inherit themeselfs. You can try to use Shapeless or Products from play json lib.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 12 '18 at 9:33









            Ivan AristovIvan Aristov

            1274




            1274








            • 1





              Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

              – Travis Brown
              Dec 12 '18 at 10:28











            • Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

              – C4stor
              Dec 12 '18 at 10:49














            • 1





              Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

              – Travis Brown
              Dec 12 '18 at 10:28











            • Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

              – C4stor
              Dec 12 '18 at 10:49








            1




            1





            Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

            – Travis Brown
            Dec 12 '18 at 10:28





            Can you clarify what "don't inherit themselves" means here? I don't see what that means or how it would help.

            – Travis Brown
            Dec 12 '18 at 10:28













            Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

            – C4stor
            Dec 12 '18 at 10:49





            Hi :-) The asker didn't specify unknown size but rather any size, which is weaker. For example, shapeless HLists (as you relevantly suggest) are definitely not of unknown size since their size is known at compile time :-) As Travis Brown, I can't quite figure what you mean in this answer, clarifying would be very helpful :-)

            – C4stor
            Dec 12 '18 at 10:49











            0














            You need to inherit your trait from Product, through which you can have productIterator, productArity and, productElement to handle the returned value. Here is an example



            case class MyClass()

            trait MyTrait[T <: Product] {
            def getMyClass(x: T): Option[MyClass] =
            if(
            x.productIterator.hasNext
            &&
            x.productIterator.next().isInstanceOf[MyClass]
            ){
            Some(x.productIterator.next().asInstanceOf[MyClass])
            } else {
            None
            }
            }

            case class Test() extends MyTrait[Product]


            And you can invoke like this



            Test().getMyClass((MyClass(), 1,3,4,5))
            //res1: Option[MyClass] = Some(MyClass())

            Test().getMyClass((1,3,4,5))
            //res2: Option[MyClass] = None


            Hope this helps you.






            share|improve this answer






























              0














              You need to inherit your trait from Product, through which you can have productIterator, productArity and, productElement to handle the returned value. Here is an example



              case class MyClass()

              trait MyTrait[T <: Product] {
              def getMyClass(x: T): Option[MyClass] =
              if(
              x.productIterator.hasNext
              &&
              x.productIterator.next().isInstanceOf[MyClass]
              ){
              Some(x.productIterator.next().asInstanceOf[MyClass])
              } else {
              None
              }
              }

              case class Test() extends MyTrait[Product]


              And you can invoke like this



              Test().getMyClass((MyClass(), 1,3,4,5))
              //res1: Option[MyClass] = Some(MyClass())

              Test().getMyClass((1,3,4,5))
              //res2: Option[MyClass] = None


              Hope this helps you.






              share|improve this answer




























                0












                0








                0







                You need to inherit your trait from Product, through which you can have productIterator, productArity and, productElement to handle the returned value. Here is an example



                case class MyClass()

                trait MyTrait[T <: Product] {
                def getMyClass(x: T): Option[MyClass] =
                if(
                x.productIterator.hasNext
                &&
                x.productIterator.next().isInstanceOf[MyClass]
                ){
                Some(x.productIterator.next().asInstanceOf[MyClass])
                } else {
                None
                }
                }

                case class Test() extends MyTrait[Product]


                And you can invoke like this



                Test().getMyClass((MyClass(), 1,3,4,5))
                //res1: Option[MyClass] = Some(MyClass())

                Test().getMyClass((1,3,4,5))
                //res2: Option[MyClass] = None


                Hope this helps you.






                share|improve this answer















                You need to inherit your trait from Product, through which you can have productIterator, productArity and, productElement to handle the returned value. Here is an example



                case class MyClass()

                trait MyTrait[T <: Product] {
                def getMyClass(x: T): Option[MyClass] =
                if(
                x.productIterator.hasNext
                &&
                x.productIterator.next().isInstanceOf[MyClass]
                ){
                Some(x.productIterator.next().asInstanceOf[MyClass])
                } else {
                None
                }
                }

                case class Test() extends MyTrait[Product]


                And you can invoke like this



                Test().getMyClass((MyClass(), 1,3,4,5))
                //res1: Option[MyClass] = Some(MyClass())

                Test().getMyClass((1,3,4,5))
                //res2: Option[MyClass] = None


                Hope this helps you.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 12 '18 at 10:00

























                answered Dec 12 '18 at 9:45









                Puneeth Reddy VPuneeth Reddy V

                901715




                901715























                    -1














                    As others said you can use shapeless:



                    import shapeless.ops.tuple.IsComposite
                    import shapeless.syntax.std.tuple._

                    class MyClass(i : Int){
                    def hello() = println(i)
                    }


                    object Tup extends App {

                    def getMyClass[P <: Product](p: P)(implicit ev: IsComposite[P]): MyClass = {
                    if (p.head.isInstanceOf[MyClass]) p.head.asInstanceOf[MyClass] else throw new Exception()
                    }
                    val x= (new MyClass(1),5,6)
                    val y = (new MyClass(2),7)

                    val c = getMyClass(x)
                    val c1 = getMyClass(y)
                    c.hello()
                    c1.hello()

                    val c2 = getMyClass((1,5,6,7)) // exception
                    c2.hello()

                    }





                    share|improve this answer
























                    • This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

                      – Travis Brown
                      Dec 12 '18 at 11:34











                    • @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 12:34











                    • Why all the casting, then?

                      – Travis Brown
                      Dec 12 '18 at 12:38











                    • @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 13:19
















                    -1














                    As others said you can use shapeless:



                    import shapeless.ops.tuple.IsComposite
                    import shapeless.syntax.std.tuple._

                    class MyClass(i : Int){
                    def hello() = println(i)
                    }


                    object Tup extends App {

                    def getMyClass[P <: Product](p: P)(implicit ev: IsComposite[P]): MyClass = {
                    if (p.head.isInstanceOf[MyClass]) p.head.asInstanceOf[MyClass] else throw new Exception()
                    }
                    val x= (new MyClass(1),5,6)
                    val y = (new MyClass(2),7)

                    val c = getMyClass(x)
                    val c1 = getMyClass(y)
                    c.hello()
                    c1.hello()

                    val c2 = getMyClass((1,5,6,7)) // exception
                    c2.hello()

                    }





                    share|improve this answer
























                    • This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

                      – Travis Brown
                      Dec 12 '18 at 11:34











                    • @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 12:34











                    • Why all the casting, then?

                      – Travis Brown
                      Dec 12 '18 at 12:38











                    • @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 13:19














                    -1












                    -1








                    -1







                    As others said you can use shapeless:



                    import shapeless.ops.tuple.IsComposite
                    import shapeless.syntax.std.tuple._

                    class MyClass(i : Int){
                    def hello() = println(i)
                    }


                    object Tup extends App {

                    def getMyClass[P <: Product](p: P)(implicit ev: IsComposite[P]): MyClass = {
                    if (p.head.isInstanceOf[MyClass]) p.head.asInstanceOf[MyClass] else throw new Exception()
                    }
                    val x= (new MyClass(1),5,6)
                    val y = (new MyClass(2),7)

                    val c = getMyClass(x)
                    val c1 = getMyClass(y)
                    c.hello()
                    c1.hello()

                    val c2 = getMyClass((1,5,6,7)) // exception
                    c2.hello()

                    }





                    share|improve this answer













                    As others said you can use shapeless:



                    import shapeless.ops.tuple.IsComposite
                    import shapeless.syntax.std.tuple._

                    class MyClass(i : Int){
                    def hello() = println(i)
                    }


                    object Tup extends App {

                    def getMyClass[P <: Product](p: P)(implicit ev: IsComposite[P]): MyClass = {
                    if (p.head.isInstanceOf[MyClass]) p.head.asInstanceOf[MyClass] else throw new Exception()
                    }
                    val x= (new MyClass(1),5,6)
                    val y = (new MyClass(2),7)

                    val c = getMyClass(x)
                    val c1 = getMyClass(y)
                    c.hello()
                    c1.hello()

                    val c2 = getMyClass((1,5,6,7)) // exception
                    c2.hello()

                    }






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Dec 12 '18 at 10:53









                    Arnon Rotem-Gal-OzArnon Rotem-Gal-Oz

                    19.3k13560




                    19.3k13560













                    • This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

                      – Travis Brown
                      Dec 12 '18 at 11:34











                    • @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 12:34











                    • Why all the casting, then?

                      – Travis Brown
                      Dec 12 '18 at 12:38











                    • @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 13:19



















                    • This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

                      – Travis Brown
                      Dec 12 '18 at 11:34











                    • @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 12:34











                    • Why all the casting, then?

                      – Travis Brown
                      Dec 12 '18 at 12:38











                    • @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

                      – Arnon Rotem-Gal-Oz
                      Dec 12 '18 at 13:19

















                    This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

                    – Travis Brown
                    Dec 12 '18 at 11:34





                    This doesn't provide any type-safety—the failure happens at runtime, not compile-time. You're not actually doing anything with Shapeless here beyond restricting the tuple to have more than one element, which isn't explicitly a requirement, anyway.

                    – Travis Brown
                    Dec 12 '18 at 11:34













                    @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

                    – Arnon Rotem-Gal-Oz
                    Dec 12 '18 at 12:34





                    @travis fair enough - though I shapeless is also used to get the first element from the tuple regardless of it and I understood that the question as 1. accept tuples of any size.2 get the MyClass from the first element from the tuple (which by the way your suggested solution does not actually do)

                    – Arnon Rotem-Gal-Oz
                    Dec 12 '18 at 12:34













                    Why all the casting, then?

                    – Travis Brown
                    Dec 12 '18 at 12:38





                    Why all the casting, then?

                    – Travis Brown
                    Dec 12 '18 at 12:38













                    @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

                    – Arnon Rotem-Gal-Oz
                    Dec 12 '18 at 13:19





                    @TravisBrown, as I said you're right about that -, could have been done better (e.g. what you did) but it does actually answer the q (how to implement getMyClass(x: T): MyClass = x._1 which works) - your solution is missing a def getMyClass(p: P) : MyClass = p.head to actually answer the question (and be typesafe )

                    – Arnon Rotem-Gal-Oz
                    Dec 12 '18 at 13:19











                    -1














                    If you are looking for compile time guarantee then this is one of the use cases for
                    Shapeless,



                    You need to add Shapeless in your build.sbt,



                    libraryDependencies ++= Seq("
                    com.chuusai" %% "shapeless" % "2.3.3"
                    )


                    Now, you can use Shapeless to define a typesafe getter which comes with compile time guarantees,



                    scala> import shapeless._
                    // import shapeless._

                    scala> import ops.tuple.IsComposite
                    // import ops.tuple.IsComposite

                    scala> import syntax.std.tuple._
                    // import syntax.std.tuple._

                    scala> case class Omg(omg: String)
                    // defined class Omg

                    scala> val myStringTuple = ("All is well", 42, "hope")
                    // myStringTuple: (String, Int, String) = (All is well,42,hope)

                    scala> val myOmgTuple = (Omg("All is well"), 42, "hope")
                    // myOmgTuple: (Omg, Int, String) = (Omg(All is well),42,hope)


                    Now if you want to enrich your tuples with a "first" getter with a specific type then,



                    scala> implicit class GetterForProduct[B <: Product](b: B) {
                    | def getFirst[A](implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined class GetterForProduct

                    scala> val myString = myStringTuple.getFirst[String]
                    // myString: String = All is well

                    scala> val myOmgError = myOmgTuple.getFirst[String]
                    // <console>:24: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = myOmgTuple.getFirst[String]
                    // ^

                    scala> val myOmg = myOmgTuple.getFirst[Omg]
                    // myOmg: Omg = Omg(All is well


                    If you don't need the implicit enrichment and are just looking for a way to "lock" the type in a getter and use it for corresponding types,



                    scala> trait FirstGetterInProduct[A] {
                    | def getFirst[B <: Product](b: B)(implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined trait FirstGetterInProduct

                    scala> object firstGetterInProductForString extends FirstGetterInProduct[String]
                    // defined object firstGetterInProductForString

                    scala> object firstGetterInProductForOmg extends FirstGetterInProduct[Omg]
                    // defined object firstGetterInProductForOmg

                    // Right tuple with right getter,
                    scala> val myString = firstGetterInProductForString.getFirst(myStringTuple)
                    // myString: String = All is well

                    // will fail at compile time for tuple with different type for first
                    scala> val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // <console>:23: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // ^

                    scala> val myOmg = firstGetterInProductForOmg.getFirst(myOmgTuple)
                    // myOmg: Omg = Omg(All is well)





                    share|improve this answer


























                    • What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

                      – jwvh
                      Dec 12 '18 at 11:52











                    • @jwvh You are right. Fixed.

                      – Sarvesh Kumar Singh
                      Dec 12 '18 at 14:08
















                    -1














                    If you are looking for compile time guarantee then this is one of the use cases for
                    Shapeless,



                    You need to add Shapeless in your build.sbt,



                    libraryDependencies ++= Seq("
                    com.chuusai" %% "shapeless" % "2.3.3"
                    )


                    Now, you can use Shapeless to define a typesafe getter which comes with compile time guarantees,



                    scala> import shapeless._
                    // import shapeless._

                    scala> import ops.tuple.IsComposite
                    // import ops.tuple.IsComposite

                    scala> import syntax.std.tuple._
                    // import syntax.std.tuple._

                    scala> case class Omg(omg: String)
                    // defined class Omg

                    scala> val myStringTuple = ("All is well", 42, "hope")
                    // myStringTuple: (String, Int, String) = (All is well,42,hope)

                    scala> val myOmgTuple = (Omg("All is well"), 42, "hope")
                    // myOmgTuple: (Omg, Int, String) = (Omg(All is well),42,hope)


                    Now if you want to enrich your tuples with a "first" getter with a specific type then,



                    scala> implicit class GetterForProduct[B <: Product](b: B) {
                    | def getFirst[A](implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined class GetterForProduct

                    scala> val myString = myStringTuple.getFirst[String]
                    // myString: String = All is well

                    scala> val myOmgError = myOmgTuple.getFirst[String]
                    // <console>:24: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = myOmgTuple.getFirst[String]
                    // ^

                    scala> val myOmg = myOmgTuple.getFirst[Omg]
                    // myOmg: Omg = Omg(All is well


                    If you don't need the implicit enrichment and are just looking for a way to "lock" the type in a getter and use it for corresponding types,



                    scala> trait FirstGetterInProduct[A] {
                    | def getFirst[B <: Product](b: B)(implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined trait FirstGetterInProduct

                    scala> object firstGetterInProductForString extends FirstGetterInProduct[String]
                    // defined object firstGetterInProductForString

                    scala> object firstGetterInProductForOmg extends FirstGetterInProduct[Omg]
                    // defined object firstGetterInProductForOmg

                    // Right tuple with right getter,
                    scala> val myString = firstGetterInProductForString.getFirst(myStringTuple)
                    // myString: String = All is well

                    // will fail at compile time for tuple with different type for first
                    scala> val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // <console>:23: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // ^

                    scala> val myOmg = firstGetterInProductForOmg.getFirst(myOmgTuple)
                    // myOmg: Omg = Omg(All is well)





                    share|improve this answer


























                    • What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

                      – jwvh
                      Dec 12 '18 at 11:52











                    • @jwvh You are right. Fixed.

                      – Sarvesh Kumar Singh
                      Dec 12 '18 at 14:08














                    -1












                    -1








                    -1







                    If you are looking for compile time guarantee then this is one of the use cases for
                    Shapeless,



                    You need to add Shapeless in your build.sbt,



                    libraryDependencies ++= Seq("
                    com.chuusai" %% "shapeless" % "2.3.3"
                    )


                    Now, you can use Shapeless to define a typesafe getter which comes with compile time guarantees,



                    scala> import shapeless._
                    // import shapeless._

                    scala> import ops.tuple.IsComposite
                    // import ops.tuple.IsComposite

                    scala> import syntax.std.tuple._
                    // import syntax.std.tuple._

                    scala> case class Omg(omg: String)
                    // defined class Omg

                    scala> val myStringTuple = ("All is well", 42, "hope")
                    // myStringTuple: (String, Int, String) = (All is well,42,hope)

                    scala> val myOmgTuple = (Omg("All is well"), 42, "hope")
                    // myOmgTuple: (Omg, Int, String) = (Omg(All is well),42,hope)


                    Now if you want to enrich your tuples with a "first" getter with a specific type then,



                    scala> implicit class GetterForProduct[B <: Product](b: B) {
                    | def getFirst[A](implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined class GetterForProduct

                    scala> val myString = myStringTuple.getFirst[String]
                    // myString: String = All is well

                    scala> val myOmgError = myOmgTuple.getFirst[String]
                    // <console>:24: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = myOmgTuple.getFirst[String]
                    // ^

                    scala> val myOmg = myOmgTuple.getFirst[Omg]
                    // myOmg: Omg = Omg(All is well


                    If you don't need the implicit enrichment and are just looking for a way to "lock" the type in a getter and use it for corresponding types,



                    scala> trait FirstGetterInProduct[A] {
                    | def getFirst[B <: Product](b: B)(implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined trait FirstGetterInProduct

                    scala> object firstGetterInProductForString extends FirstGetterInProduct[String]
                    // defined object firstGetterInProductForString

                    scala> object firstGetterInProductForOmg extends FirstGetterInProduct[Omg]
                    // defined object firstGetterInProductForOmg

                    // Right tuple with right getter,
                    scala> val myString = firstGetterInProductForString.getFirst(myStringTuple)
                    // myString: String = All is well

                    // will fail at compile time for tuple with different type for first
                    scala> val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // <console>:23: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // ^

                    scala> val myOmg = firstGetterInProductForOmg.getFirst(myOmgTuple)
                    // myOmg: Omg = Omg(All is well)





                    share|improve this answer















                    If you are looking for compile time guarantee then this is one of the use cases for
                    Shapeless,



                    You need to add Shapeless in your build.sbt,



                    libraryDependencies ++= Seq("
                    com.chuusai" %% "shapeless" % "2.3.3"
                    )


                    Now, you can use Shapeless to define a typesafe getter which comes with compile time guarantees,



                    scala> import shapeless._
                    // import shapeless._

                    scala> import ops.tuple.IsComposite
                    // import ops.tuple.IsComposite

                    scala> import syntax.std.tuple._
                    // import syntax.std.tuple._

                    scala> case class Omg(omg: String)
                    // defined class Omg

                    scala> val myStringTuple = ("All is well", 42, "hope")
                    // myStringTuple: (String, Int, String) = (All is well,42,hope)

                    scala> val myOmgTuple = (Omg("All is well"), 42, "hope")
                    // myOmgTuple: (Omg, Int, String) = (Omg(All is well),42,hope)


                    Now if you want to enrich your tuples with a "first" getter with a specific type then,



                    scala> implicit class GetterForProduct[B <: Product](b: B) {
                    | def getFirst[A](implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined class GetterForProduct

                    scala> val myString = myStringTuple.getFirst[String]
                    // myString: String = All is well

                    scala> val myOmgError = myOmgTuple.getFirst[String]
                    // <console>:24: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = myOmgTuple.getFirst[String]
                    // ^

                    scala> val myOmg = myOmgTuple.getFirst[Omg]
                    // myOmg: Omg = Omg(All is well


                    If you don't need the implicit enrichment and are just looking for a way to "lock" the type in a getter and use it for corresponding types,



                    scala> trait FirstGetterInProduct[A] {
                    | def getFirst[B <: Product](b: B)(implicit comp: IsComposite[B] { type H = A }): A = b.head
                    | }
                    // defined trait FirstGetterInProduct

                    scala> object firstGetterInProductForString extends FirstGetterInProduct[String]
                    // defined object firstGetterInProductForString

                    scala> object firstGetterInProductForOmg extends FirstGetterInProduct[Omg]
                    // defined object firstGetterInProductForOmg

                    // Right tuple with right getter,
                    scala> val myString = firstGetterInProductForString.getFirst(myStringTuple)
                    // myString: String = All is well

                    // will fail at compile time for tuple with different type for first
                    scala> val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // <console>:23: error: could not find implicit value for parameter comp: shapeless.ops.tuple.IsComposite[(Omg, Int, String)]{type H = String}
                    // val myOmgError = firstGetterInProductForString.getFirst(myOmgTuple)
                    // ^

                    scala> val myOmg = firstGetterInProductForOmg.getFirst(myOmgTuple)
                    // myOmg: Omg = Omg(All is well)






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Dec 12 '18 at 14:08

























                    answered Dec 12 '18 at 11:32









                    Sarvesh Kumar SinghSarvesh Kumar Singh

                    8,3411935




                    8,3411935













                    • What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

                      – jwvh
                      Dec 12 '18 at 11:52











                    • @jwvh You are right. Fixed.

                      – Sarvesh Kumar Singh
                      Dec 12 '18 at 14:08



















                    • What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

                      – jwvh
                      Dec 12 '18 at 11:52











                    • @jwvh You are right. Fixed.

                      – Sarvesh Kumar Singh
                      Dec 12 '18 at 14:08

















                    What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

                    – jwvh
                    Dec 12 '18 at 11:52





                    What is the "compile time guarantee" here? The OP has requested that tuples of any length, but only with the 1st element of a specific type, be accepted. (Not my down-vote.)

                    – jwvh
                    Dec 12 '18 at 11:52













                    @jwvh You are right. Fixed.

                    – Sarvesh Kumar Singh
                    Dec 12 '18 at 14:08





                    @jwvh You are right. Fixed.

                    – Sarvesh Kumar Singh
                    Dec 12 '18 at 14:08


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53739656%2fscala-generic-tuple%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Probability when a professor distributes a quiz and homework assignment to a class of n students.

                    Aardman Animations

                    Are they similar matrix