softwaremill / magnolia

Easy, fast, transparent generic derivation of typeclass instances
https://softwaremill.com/open-source/
Apache License 2.0
768 stars 117 forks source link

Derivation with "exists" semantics #61

Open joroKr21 opened 6 years ago

joroKr21 commented 6 years ago

What I mean is what if to create a type class for the whole case class / sealed trait I only need the instance for one field / subtype (or a subset of all fields / subtypes)? Like finding a field of some type deep within the structure.

E.g. Default only uses the first subtype instance. In fact it could be any instance. The rest of the subtype instances don't even need to exist.

I'm not sure if #46 would enable this?

propensive commented 6 years ago

I think I understand, and I think something would be possible with #46, though if you have a concrete example, I would probably be more certain that I'm understanding correctly!

joroKr21 commented 6 years ago

One example is Default for a sealed trait:

sealed trait MaybeDate
case class ADate(date: Date) extends MaybeDate
case object NoDate extends MaybeDate

If I don't have a default Date I should still have a default MaybeDate by virtue of NoDate.

In general for any coproduct A :+: B :+: C :+: CNil there should be a Default instance whenever there exists a default instance for at least one of A, B or C. With shapeless I can express this like so (note the missing instance for CNil):

implicit def defaultLeft[L, R <: Coproduct](implicit L: Default[L]): Default[L :+: R] = ...
implicit def defaultRigth[L, R <: Coproduct](implicit R: Default[R]): Default[L :+: R] = ...
propensive commented 6 years ago

That's a pretty clear example, thanks. I think we can offer a dispatch parameter which provides a non-empty list of derived typeclasses. (This will probably make more sense when I finally merge #46.) It needs a bit of reworking to ensure derivation continues even when not every branch of the coproduct can be derived, but should be doable.