Skip to content

Instantly share code, notes, and snippets.

@vivanov
Last active April 11, 2021 05:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vivanov/368960402c52ee943a7e1acfd6ac8023 to your computer and use it in GitHub Desktop.
Save vivanov/368960402c52ee943a7e1acfd6ac8023 to your computer and use it in GitHub Desktop.
Question about nested Objects and tagles final
import cats.Functor
import cats.syntax.functor._
import cats.effect.IO
import doobie.util.composite.Composite
import shapeless.{ HList, HNil}
import shapeless.ops.hlist.Mapper
import shapeless.ops.hlist.RightFolder
import shapeless.ops.hlist.ZipConst
case class TableContextF[F[_], S, T: Composite](tableName: String, columns: List[String], cc2compositeF: S => F[T])
object TableContextF {
def apply[F[_]: Functor, S](tableName: String) = {
new Object {
def apply[T](f: S => F[T]) = {
new Object {
private object GetColumns extends shapeless.Poly2 {
implicit def atS0[S0] =
at[(String, S0), List[String]] { case ((c, _), cs) => c :: cs }
}
private object GetExtractor extends shapeless.Poly1 {
implicit def atS0[S0] =
at[(String, S0)](_._2)
}
private object ApplyExtractor extends shapeless.Poly1 {
implicit def atS0T[S0, T0] =
at[(S0 => T0, S0)] { case (e, s) => e(s) }
}
def apply[T1: Composite](c1: String, e1: T => T1) = getContext(f)((c1, e1) :: HNil)
def apply[T1: Composite, T2: Composite](c1: String, e1: T => T1, c2: String, e2: T => T2) =
getContext(f)((c1, e1) :: (c2, e2) :: HNil)
def apply[T1: Composite, T2: Composite, T3: Composite](
c1: String,
e1: T => T1,
c2: String,
e2: T => T2,
c3: String,
e3: T => T3
) = getContext(f)((c1, e1) :: (c2, e2) :: (c3, e3) :: HNil)
def apply[T1: Composite, T2: Composite, T3: Composite, T4: Composite](
c1: String,
e1: T => T1,
c2: String,
e2: T => T2,
c3: String,
e3: T => T3,
c4: String,
e4: T => T4
) = getContext(f)((c1, e1) :: (c2, e2) :: (c3, e3) :: (c4, e4) :: HNil)
//... more similar methods
private def getContext[M <: HList, MR <: HList, ZR <: HList, AR <: HList](f: S => F[T])(mapping: M)(
implicit columnFolder: RightFolder.Aux[M, List[String], GetColumns.type, List[String]],
extractorMapper: Mapper.Aux[GetExtractor.type, M, MR],
ccZipper: ZipConst.Aux[T, MR, ZR],
applyMapper: Mapper.Aux[ApplyExtractor.type, ZR, AR],
composite: Composite[AR]
) = {
val extractors = mapping.map(GetExtractor)
new TableContextF(
tableName,
mapping.foldRight(List[String]())(GetColumns),
(cc: S) => f(cc).map(extractors.zipConst(_).map(ApplyExtractor))
)
}
}
}
}
}
case class CC(a: Int, b: Long, c: String)
def tableContext = TableContextF[IO, CC]("cc_table")(Functor[IO]) { s =>
IO(s -> Some("other stuff"))
}(
"col_a",
_._1.a,
"col_b",
_._1.b,
"col_c",
_._1.c,
"col_d",
_._2
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment