Closed fommil closed 6 years ago
This seems to be a goer... but I'm unhappy with it because it requires the typeclass author to consider four cases. Shapeless doesn't allow for massive divide/conquer and always folds left, so it only considers the case equivalent to case (Solo(fa), Label(fb, lb))
(this means it can never be as efficient as scalaz-deriving
)
I need to top and tail this, but I am also investigating using type members to be able to dramatically simplify the approach.
sealed trait L[F[_], A]
final case class Label[F[_], A](fa: F[A], label: String) extends L[F, A]
final case class Solo[F[_], A](fa: F[A]) extends L[F, A]
implicit val tcdShow: LazyDivisible[L[Show, ?]] =
new LazyDivisible[L[Show, ?]] {
def conquer[A]: L[Show, A] = Solo(Show.shows(_ => ""))
def divide2[A, B, C](fa: => L[Show, A], fb: => L[Show, B])(
f: C => (A, B)
): L[Show, C] = Solo(
Show.shows { c =>
val (a, b) = f(c)
(fa, fb) match {
case (Label(fa, la), Label(fb, lb)) =>
s"$la=${fa.shows(a)},$lb=${fb.shows(b)}"
case (Label(fa, la), Solo(fb)) =>
s"$la=${fa.shows(a)},${fb.shows(b)}"
case (Solo(fa), Label(fb, lb)) =>
s"${fa.shows(a)},$lb=${fb.shows(b)}"
case (Solo(fa), Solo(fb)) =>
s"${fa.shows(a)},${fb.shows(b)}"
}
}
)
}
(yeah, I know it'd be more efficient with Cord
and that I'm missing a F[C] => F[C]
call at the end to wrap with Foo(...)
... this is just a PoC)
ok... I think this is nearly beat. How about abstracting over arity with one of these bad boys?
trait Field[F[_]] {
type A
def label: String
def value: A
def typeclass: F[A]
}
def shown[A](parts: IList[Field[Show]]): String =
parts.map { applied =>
applied.typeclass.shows(applied.value)
}.intercalate(",")
all credit to @non
I'm pretty sure this allows us to abstract over arity for applyX
and divideX
, e.g.
def divideX[C[_]: Foldable, Z](f: Z => C[Field[F]]): F[Z]
PR in #1565
This was originally opened as a question about Divisible.conquer but morphed into the realisation that
scalaz-deriving
will need an invariant parent of Apply and Divide to support typeclass derivation.I'll pick this up... I'll create a fresh hierarchy in the stalactite repo and ask for comments there but I'd very much like to get a bincompat version of this into 7.2
original ticket follows:
how can this ever work? In scala we'd typically need to take evidence for
Divisible[A]
in theconquer
parameter, the current signature means that we must ignore theA
.In
scalaz-deriving
I'm probably going to base contravariant derivations onDivide
(or some variant with labels)// @xuwei-k (you touched it last)