/
GenericAutoRow.scala
64 lines (54 loc) · 2.32 KB
/
GenericAutoRow.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package astrac.boxtables
import cats.syntax.contravariant._
import shapeless.ops.hlist.{At, ZipConst, ZipWithIndex}
import shapeless.{Generic, HList, Nat, Poly1}
import shapeless.ops.hlist.{LiftAll, Mapper, ToList}
trait GenericAutoRow[Primitive, Model] {
def row: GenericRow[Primitive, Model]
}
object GenericAutoRow {
object mapper extends Poly1 {
implicit def instance[Primitive,
Content,
Model,
Index <: Nat,
Repr <: HList](
implicit hlistAt: At.Aux[Repr, Index, Content]) =
at[((GenericCell[Primitive, Content], Index), Generic.Aux[Model, Repr])] {
case ((cell, _), generic) =>
cell.contramap[Model](m => generic.to(m).at[Index])
}
}
implicit def instance[Primitive,
Model,
Repr <: HList,
Cells <: HList,
IndexedCells <: HList,
Args <: HList,
ContramappedCells <: HList](
implicit generic: Generic.Aux[Model, Repr],
liftCells: LiftAll.Aux[GenericCell[Primitive, ?], Repr, Cells],
indexed: ZipWithIndex.Aux[Cells, IndexedCells],
withGeneric: ZipConst.Aux[Generic.Aux[Model, Repr], IndexedCells, Args],
cellsContramapper: Mapper.Aux[mapper.type, Args, ContramappedCells],
toList: ToList[ContramappedCells, GenericCell[Primitive, Model]]
): GenericAutoRow[Primitive, Model] =
new GenericAutoRow[Primitive, Model] {
override val row = GenericRow.instance(
liftCells.instances.zipWithIndex.zipConst(generic).map(mapper).toList)
}
trait Instances {
implicit def rowInstance[Primitive, Model](
implicit r: GenericAutoRow[Primitive, Model])
: GenericRow[Primitive, Model] =
GenericAutoRow[Primitive, Model]
}
object instances extends Instances
def apply[Primitive, Model](implicit r: GenericAutoRow[Primitive, Model])
: GenericRow[Primitive, Model] = r.row
def derive[Primitive, Model](implicit r: GenericAutoRow[Primitive, Model])
: GenericRow[Primitive, Model] = apply
def formatted[Primitive, Model](f: GenericFormatter[Primitive])(
implicit r: GenericAutoRow[Primitive, Model])
: GenericRow[Primitive, Model] = derive[Primitive, Model].format(f)
}