How to access default values for case class fields?

Viewed 150

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] = ???
0 Answers
Related