I want to derive instances of some type (Decoder[A]
) for arbitrary case classes using shapeless
.
trait Decoder[A] extends Serializable { self =>
def decode(source: String): Either[Throwable, A]
}
If i don't consider the default values for case class then all is going well using the basic approach:
final implicit def genericDecoder[A, H <: HList](
implicit gen: LabelledGeneric.Aux[A, H],
hDecoder: Lazy[Decoder[H]]
): Decoder[A] = value => hDecoder.value.decode(value).map(gen.from)
final implicit val hnilDecoder: Decoder[HNil] = ???
final implicit def hlistDecoder[K <: Symbol, H, T <: HList](
implicit witness: Witness.Aux[K],
hDecoder: Lazy[Decoder[H]],
tDecoder: Lazy[Decoder[T]]
): Decoder[FieldType[K, H] :: T] = ???
Now i want to be able to use a default value for field which can't be decoded. In this case i tried this approach (add additional abstraction layer):
trait DecoderWithDefaults[A, B] extends Serializable {
def decode(value: String, defaults: B): Either[Throwable, A]
}
final implicit def genericDecoder[A, H <: HList, HD <: HList](
implicit gen: LabelledGeneric.Aux[A, H],
defaults: Default.AsOptions.Aux[A, HD],
hDecoder: Lazy[DecoderWithDefaults[H, HD]]
): Decoder[A] = value => hDecoder.value.decode(value, defaults()).map(gen.from)
final implicit val hnilDecoder: DecoderWithDefaults[HNil, HNil] = (_, _) => Right(HNil)
final implicit def hlistDecoder[K <: Symbol, H, T <: HList, TD <: HList](
implicit witness: Witness.Aux[K],
hDecoder: Lazy[DecoderWithDefaults[H, Option[H]]],
tDecoder: Lazy[DecoderWithDefaults[T, TD]]
): DecoderWithDefaults[FieldType[K, H] :: T, Option[H] :: TD] = ???
So, my question is: is it possible to achieve the same but without using additional abstraction layer (like DecoderWithDefaults
in this case)? Something like:
final implicit def hlistDecoder[K <: Symbol, H, T <: HList](
implicit witness: Witness.Aux[K],
defaultValueHead: Option[H],
hDecoder: Lazy[Decoder[H]],
tDecoder: Lazy[Decoder[T]]
): Decoder[FieldType[K, H] :: T] = ???