I have a simple case class that represents a pet:
case class Pet(name: String, age: Int)
Now say I have a case class that has a 1:1 mapping to Pet, but where all of the properties have been wrapped in some sort of "resolveable" container or monad:
case class ResolveableToPet(name: Future[String], age: Some[Int])
The transformation from the latter to the former is quite simple to define:
def resolvePet(rPet: ResolveableToPet)(implicit ec: ExecutionContext): Future[Pet] =
rPet.flatMap(Pet(_, rPet.age.value))
Noticing that Future's flatMap and Some's value in some sense both "extract the value from within the container", I expect we could define an "extractor" typeclass that could treat them both equally, and thus would allow us – with enough work – to define resolvePet generically.
Maybe it would even look roughly something like this after all is said and done:
def resolve[R, T](resolveable: R)(implicit resolver: Resolver[R, T]): T =
resolver.resolve(resoleveable)
I feel that this isn't even particularly a difficult or challenging problem, and having worked with cats often enough I'm noticing that this seems to align highly with the tools it provides. Such that I suspect that this has already been solved and I simply don't know the name by which to refer to this.
Is there a existing tooling – perhaps in cats, kittens, or scalaz – that solves this problem for me, or maybe simply gets me 75% of the way there?
Unfortunatelly, can't advice you auto deriving decision but I have one concise and not ugly solution. Take a look at Chimney library - it is very usefull library to make conversions between case classes. I write a simple example for you purposes but I'm sure, you can easily write another one more complex based on examples from documentation
You can use same transformerFSupport for the same
F[_]type and not write a lot of code to simple map case class into another.