Since there is no relation between FunctionN types in Scala, this cannot be done without a level-level template somewhere - there is simply no way to abstract from the methods of related apply objects without listing all possible number of members.
You can do this manually using the CompanionN[A, B, C, ...] feature set CompanionN[A, B, C, ...] , but it is rather annoying. Shapeless provides a much better solution for writing something like the following:
import shapeless.{ Generic, HList }, shapeless.ops.product.ToHList class CaseClassCompanion[C] { def tupled[P <: Product, R <: HList](p: P)(implicit gen: Generic.Aux[C, R], toR: ToHList.Aux[P, R] ): C = gen.from(toR(p)) }
And then:
case class Book(id: Int, isbn: String, name: String) object Book extends CaseClassCompanion[Book] case class Author(id: Int, name: String) object Author extends CaseClassCompanion[Author]
What you can use as follows:
scala> Book.tupled((0, "some ISBN", "some name")) res0: Book = Book(0,some ISBN,some name) scala> Author.tupled((0, "some name")) res1: Author = Author(0,some name)
Perhaps you donβt even need a part of CaseClassCompanion , since you can build a general method that converts tuples to case classes (provided that the type members line up):
class PartiallyAppliedProductToCc[C] { def apply[P <: Product, R <: HList](p: P)(implicit gen: Generic.Aux[C, R], toR: ToHList.Aux[P, R] ): C = gen.from(toR(p)) } def productToCc[C]: PartiallyAppliedProductToCc[C] = new PartiallyAppliedProductToCc[C]
And then:
scala> productToCc[Book]((0, "some ISBN", "some name")) res2: Book = Book(0,some ISBN,some name) scala> productToCc[Author]((0, "some name")) res3: Author = Author(0,some name)
This will work for case classes with up to 22 members (since the apply method on a companion object cannot be eta-extended to a function if there are more than 22 arguments).