glittershark glittershark - 5 months ago 42
Scala Question

Map a tagged HList (record) of functions over a record of their argument types

I'm (in effect, this is all simplified from my working example) trying to map a tagged HList (a record) of contravariant (constant return value, polymorphic argument type) functions over a record consisting of the proper argument types of those functions.
I'm aware of ZipApply, and that seems to work for HLists, but I specifically want to do this regardless of order and specifically use the key types to select which functions to use.

Here's my code example, which isn't compiling for reasons I can't figure out:

import shapeless._
import labelled._
import ops.hlist._
import ops.record.Selector
import syntax._
import syntax.singleton._
import syntax.HListOps

object POC {
case class Foo(bar: String)
val gen = LabelledGeneric[Foo]
val funs = ('bar ->> { s: String => s.toUpperCase() }) :: HNil

val poly = new Poly1 {
implicit def apply[K, V]
(implicit selector: Selector.Aux[funs.type, K, (V) => String]) =
at[FieldType[K, V]] { v => selector(funs)(v) }

def run(foo: Foo)(implicit mapper: Mapper[poly.type, gen.Repr]) =
mapper(gen to foo)

// could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[POC.<refinement>.type,POC.gen.Repr]


The issue here is that poly isn't a stable identifier, or it's not stable enough, or something like that. The following will work just fine:

object poly extends Poly1 { ... }

I'm not sure I've seen a much better explanation of what's going on here than Miles's comment on this answer of mine (which is now four and a half years old).