arainko / ducktape

Automatic and customizable compile time transformations between similar case classes and sealed traits/enums, essentially a thing that glues your code. Scala 3 only. Or is it duct 🤔
https://arainko.github.io/ducktape/
Other
405 stars 7 forks source link

On-fly transformations aka row polymorphism #107

Closed chuwy closed 10 months ago

chuwy commented 10 months ago

I recently got an idea for library, but after I started implementing it - I see there's a lot of machinery in ducktape that looks very similar. Maybe ducktape itself can benefit from including this feature.

Basically, the idea is to implement row polymorphism via givens:

case class Person(name: String, age: Int)
case class Student(name: String, age: Int, university: String)

def checkin[P](p: P)(using Row[Person, P]): IO[P] =
  doTheStuff(p.name, p.age)

checkin(Student("Joe", 27, "Oxford"))        // ok
checkin(Person("Bob", 21))                   // ok

Let me know if you think it's out of scope of ducktape.

arainko commented 10 months ago

That kind of looks like a nicer way of writing this:

case class Person(name: String, age: Int)
case class Student(name: String, age: Int, university: String)

def checkin[P](p: P)(using t: Transformer[P, Person]): IO[P] = {
  val person = t.transform(p)
  doTheStuff(person.name, person.age)
}

checkin(Student("Joe", 27, "Oxford"))        // ok
checkin(Person("Bob", 21))                   // ok

so I'd say it's not really in scope for ducktape - what's more, I'm not sure if your proposed syntax is even possible without some type refinement astronautics or else the compiler won't able to tell you if p.name is possible at all.

Or if you're feeling crazy enough (pseudo code, dunno if it works):

given [A, B](using t: Transformer[A, B]: Conversion[A, B] = t.transform

case class Person(name: String, age: Int)
case class Student(name: String, age: Int, university: String)

def checkin[P](p: P)(using Conversion[P, Person]): IO[P] =
  doTheStuff(p.name, p.age)