shapeless: Generic programming for Scala | This room deprecated in favour of #shapeless on the Typelevel Discord: https://discord.gg/bSQBZA3Ced
joroKr21 on main
Remove refinement from Witness.… Merge branch 'main' into witnes… Merge branch 'main' into witnes… and 2 more (compare)
joroKr21 on main
Update sbt to 1.7.1 Merge pull request #1263 from s… (compare)
joroKr21 on main
Update junit-plugin, junit-runt… Revert commit(s) ca4fe1de Merge branch 'main' into update… and 2 more (compare)
joroKr21 on main
Update sbt-scalajs, scalajs-com… Merge branch 'main' into update… Merge pull request #1260 from s… (compare)
joroKr21 on main
Update scala-compiler, scala-li… Merge pull request #1261 from s… (compare)
import shapeless._, ops.hlist._, poly._, labelled._
trait Describe[A] {
def apply(a: A): String
}
object Describe {
def apply[A](a: A)(implicit ev: Describe[A]) = ev(a).dropRight(2)
implicit def all[A](
implicit f: Case.Aux[body.type, A :: HNil, String]): Describe[A] =
new Describe[A] {
def apply(a: A) = f.apply(a)
}
object body extends Compose(describer, flatten)
object describer extends LowPrioDescriber {
implicit def all[H <: HList](
implicit fm: MapFolder[H, String, describer.type]) =
at[H](x => fm(x, "", _ + _))
}
trait LowPrioDescriber extends Poly1 {
implicit def base[K <: Symbol, V](implicit key: Witness.Aux[K]) =
at[FieldType[K, V]](x => s"${key.value.name} = ${x.toString}, ")
}
object flatten extends LowPrioFlatten {
implicit def hlists[H <: HList](
implicit fm: Lazy[FlatMapper[flatten.type, H]]) =
at[H](x => fm.value(x))
implicit def kv[K, V, R](implicit gen: LabelledGeneric.Aux[V, R],
rec: Lazy[Case1[flatten.type, R]]) =
at[FieldType[K, V]](x => rec.value(gen.to(x)))
implicit def prods[A, R <: HList](
implicit gen: LabelledGeneric.Aux[A, R],
rec: Lazy[Case1[flatten.type, R]]) =
at[A](x => rec.value(gen.to(x)))
}
trait LowPrioFlatten extends Poly1 {
implicit def all[A] = at[A](x => x :: HNil)
}
}
case class Foo(a: String, b: Bar)
case class Bar(c: Int, d: Baz)
case class Baz(e: Long)
val v = Foo("A", Bar(1, Baz(2)))
def c = Describe(v)
// res1: String = a = A, c = 1, e = 2
List
describer
probably needs some modification, it doesn't compile if your case classes have List
s in them
List
Option
, and in general, data types with alternatives?
Baz
and a List
?
Poly
towards a custom type class (even though you get to keep, with small adaptations, most of the code in the instances)
Lists
to be printed differently, e.g. 1..2
, add an instance to describer
forTraversable()
List
s to be printed differently which is why I added an implicit def
to construct a type class for List[Int]
. it should display lists as [1,2]
Describe
is not being resolved recursively
[1,2,3]
and so on right? or [1]
if they have one element
Poly
s
<: HList
to the R
type parameter in kv
base
in LowPrioDescriber
to take an implicit f: Format[V]
where Format
is a typeclass that converts types to String
.toString
with f(x: V)
Format
sounds similar to Describe
, it's because it is! Hence my point about all this being probably better if rewritten from scratch as a recursive typeclass
LabelledGeneric#Repr
type to get access to the field names later
HList
s themselves though. here's the latest: https://scalafiddle.io/sf/8e8Kbup/4
HList
since it can't create LabelledGeneric
for the example I tried. makes sense. :)