1

I know this question is deep type level programming and my failure is due to lack of knowledge. but I'd like to know at least how to get this one to compile. I need the compiler to figure out that my tuple2 can be a Higher-Kinded type in the context.

trait Extract[T[_],A]{
  def extract(t: T[A]): A
}

object Extract{
  type T2[B] = {type l[X] = (X,B)}
  implicit def forTuple2[A,B] = new Extract[T2[B]#l,A] {

    override def extract(t: (A, B)): A = t._1
  }
}

def method[T[_],A](a: T[A])(implicit extractor: Extract[T,A]): A = extractor.extract(a)
method[Extract.T2[String]#l,Int]((1,"hi")) //this works but is useless. 
//the whole point is to get the compiler to do the heavy lifting And in 
//this case it means inferring that a tuple2 of (X,whatever) is a T[X] for the context

anything as much close to my goal as possible is appreciated. I also know shapeless has a library dedicated to this stuff. but let's assume shapeless doesn't exist to solve my problem.

shayan
  • 1,211
  • 9
  • 12

1 Answers1

2

The compiler has no way of knowing if you want type T[X] = Tuple2[X, A] or T[X] = Tuple2[X, A], so it gives up even before looking at the implicit parameter. You were on the right track with an implicit, except that in this case you don't even need to go through a type lambda (you don't case about seeing Tuple2[_, A] as T[A]):

def method[X, A](x: X)(implicit ev: Open[X, A]): A =
  ev.open(x)

Open specifies which hole of the Tuple2 you want to use:

trait Open[X, Out] {
  def open(x: X): Out
}

object Open {
  implicit def firsthole[A, B] = new Open[Tuple2[A, B], A] {
    def open(x: Tuple2[A, B]) = x._1
  }
}

I know this question is deep type level programming

Deep? You ain't seen nothing yet ( ͡° ͜ʖ ͡°)

OlivierBlanvillain
  • 7,701
  • 4
  • 32
  • 51