3

I have gone through some of the Qs here on the same matter but can't seem to be able to find a solution for my case.

In essence I would need to define a method that accepts an x, where x <: T and an l, where L <: HList and map over l using a Poly1 defined in each possible class that inherits from T.

I've tried in several ways and my last attempt resulted in some pretty scary scalac bomb. I must be doing something really stupid but can't seem to get my head around it!

import shapeless._
import ops.hlist._

trait T {
  val fun: Poly1
}
case class C() extends T {
  object fun extends Poly1 {
    implicit val caseInt = at[Int](i => "int " + i)
    override def toString = "here I am, poly1"
  }
}
def method[X <: T](x: X) = x.fun
method(C())
res0: shapeless.Poly1 = here I am, poly1

def method2[X <: T, L <: HList](x: X, l: L)(implicit m: Mapper[x.fun.type, L]) = l map x.fun
method(C(), 23 :: HNil) //BOOM!
jsirocchi
  • 556
  • 4
  • 4
  • As I just mentioned on Twitter, you're [probably out of luck](http://stackoverflow.com/questions/11442440/unable-to-map-on-hlist/11442871#comment15099885_11442871) here. – Travis Brown Jun 10 '14 at 00:40
  • What @TravisBrown said ... `C()` is volatile which will frustrate the implicit search for cases of `fun`. – Miles Sabin Jun 10 '14 at 06:54

1 Answers1

1

I don't know if this is exactly what you want, but it works:

object test {

import shapeless._
import ops.hlist._

  trait T {

    type PT <: Singleton with Poly1
    val fun: PT
  }

  object C extends T {

    type PT = funImpl.type
    object funImpl extends Poly1 {
      implicit val caseInt = at[Int](i => "int " + i)
      override def toString = "here I am, poly1"
    }
    val fun = funImpl
  }

  case class D() extends T {

    type PT = funImpl.type
    object funImpl extends Poly1 {
      implicit val caseInt = at[Int](i => "int " + i)
      override def toString = "here I am, poly1"
    }
    val fun = funImpl
  }


  def method[X <: T](x: X) = x.fun
  val ok = method(C)

  // singletonize it
  implicit def toOps[X <: T](x: X): Method2Ops[x.type] = { Method2Ops(x: x.type) }
  case class Method2Ops[X <: Singleton with T](val x: X) {

    def method2[L <: HList](l: L)(implicit m: Mapper[X#PT, L]) = l map (x.fun: X#PT)
  }

  val okC =  C method2 (23 :: HNil)

  val d = D()

  val okD = d method2 (23 :: HNil)
}
Eduardo Pareja Tobes
  • 3,060
  • 1
  • 18
  • 19
  • can I say that the essence of the trick is that in the implicit conversion you pass `x: x.type` and in `Method2Ops` you require a singleton? what else is important here? – laughedelic Jun 17 '14 at 23:33