All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.kodeworks.kvarg.util.CopySyntax.scala Maven / Gradle / Ivy

There is a newer version: 0.7
Show newest version
package no.kodeworks.kvarg.util

import shapeless._

// Implementation in terms of LabelledGeneric ...
object mergeSyntax {
  implicit class MergeSyntax[T](t: T) {
    def merge[U](u: U)(implicit merge: CaseClassMerge[T, U]): T = merge(t, u)
  }
}

trait CaseClassMerge[T, U] {
  def apply(t: T, u: U): T
}

object CaseClassMerge {
  import ops.record.Merger

  def apply[T, U](implicit merge: CaseClassMerge[T, U]): CaseClassMerge[T, U] = merge

  implicit def mkCCMerge[T, U, RT <: HList, RU <: HList]
  (implicit
   tgen: LabelledGeneric.Aux[T, RT],
   ugen: LabelledGeneric.Aux[U, RU],
   merger: Merger.Aux[RT, RU, RT]
  ): CaseClassMerge[T, U] =
    (t: T, u: U) => tgen.from(merger(tgen.to(t), ugen.to(u)))
}

// Implementation in terms of RecordArgs, Generic and Lazy ...
object copySyntax {
  class CopySyntax[T](t: T) {
    object copy extends RecordArgs {
      def applyRecord[R <: HList](r: R)(implicit update: UpdateRepr[T, R]): T = update(t, r)
    }
  }

  implicit def apply[T](t: T): CopySyntax[T] = new CopySyntax[T](t)
}

object openCopySyntax {
  class CopySyntax[T, BaseFields0](t: OpenFamily[T] { type BaseFields = BaseFields0 }) {
    object copy extends RecordArgs {
      def applyRecord[R <: HList](r: R)(implicit update: UpdateRepr[BaseFields0, R]): T =
        t.baseCopy(update(t.baseFields, r))
    }
  }

  implicit def apply[T](t: OpenFamily[T]): CopySyntax[T, t.BaseFields] = new CopySyntax(t)
}

trait OpenFamily[T] {
  type BaseFields
  def baseFields: BaseFields
  def baseCopy(base: BaseFields): T
}

trait UpdateRepr[T, R <: HList] {
  def apply(t: T, r: R): T
}

object UpdateRepr {
  import ops.record._

  implicit def mergeUpdateRepr[T <: HList, R <: HList]
  (implicit merger: Merger.Aux[T, R, T]): UpdateRepr[T, R] =
    (t: T, r: R) => merger(t, r)

  implicit def cnilUpdateRepr[R <: HList]: UpdateRepr[CNil, R] =
    (t: CNil, r: R) => t

  implicit def cconsUpdateRepr[H, T <: Coproduct, R <: HList]
  (implicit
   uh: Lazy[UpdateRepr[H, R]],
   ut: Lazy[UpdateRepr[T, R]]
  ): UpdateRepr[H :+: T, R] =
    (t: H :+: T, r: R) => t match {
      case Inl(h) => Inl(uh.value(h, r))
      case Inr(t) => Inr(ut.value(t, r))
    }

  implicit def genProdUpdateRepr[T, R <: HList, Repr <: HList]
  (implicit
   prod: HasProductGeneric[T],
   gen: LabelledGeneric.Aux[T, Repr],
   update: Lazy[UpdateRepr[Repr, R]]
  ): UpdateRepr[T, R] =
    (t: T, r: R) => gen.from(update.value(gen.to(t), r))

  implicit def genCoprodUpdateRepr[T, R <: HList, Repr <: Coproduct]
  (implicit
   coprod: HasCoproductGeneric[T],
   gen: Generic.Aux[T, Repr],
   update: Lazy[UpdateRepr[Repr, R]]
  ): UpdateRepr[T, R] =
    new UpdateRepr[T, R] {
      def apply(t: T, r: R): T = gen.from(update.value(gen.to(t), r))
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy