I'm trying to come up with something similar to Classy Lenses to use with cats-mtl. For this, I want to be able to construct a Lens based on provided types only. I found no way to do it using operations provided in shapeless, so I'm writing a new one.
import shapeless._
class Classy[O[_, _], S, A](val get: O[S, A])
object Classy {
def apply[O[_, _], S, A](implicit ev: Classy[O, S, A]): Classy[O, S, A] = ev
implicit def rootLens[S]: Classy[Lens, S, S] =
new Classy(OpticDefns.id[S])
implicit def elementLens[S, L <: HList, A](
implicit genLens: MkGenericLens.Aux[S, L],
aLens: MkHListSelectLens[L, A]
): Classy[Lens, S, A] = new Classy(aLens() compose genLens())
implicit def composeLens[S, A, T](
implicit lh: Lazy[Classy[Lens, S, A]],
rh: Classy[Lens, A, T]
): Classy[Lens, S, T] = new Classy(rh.get compose lh.value.get)
}
Unfortunately, the case I'm after is not compiling:
Classy[Lens, String, String] // OK
Classy[Lens, (Long, String), String] // OK
Classy.composeLens[(Int, (Long, String)), (Long, String), String] // OK, explicit call with explicit params
//Classy[Lens, (Int, (Long, String)), String] // <- doesn't compile
I tried a number of combinations with Lazy
/ Strict
/ plain implicit, but none of these have worked.
Try the following approach with redefining operations making them work deeper:
Motivated by example https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/deephlister.scala