Search code examples
scalashapelesstype-level-computationpath-dependent-type

How to use a path dependent type class


I'm trying to use a type-dependent type class in a method as below:

@typeclass trait Identifiable[M] {
  type K
  def identify(id: M): K
}

object Identifiable {
  type Aux[M, K0] = Identifiable[M] { type K = K0 }
  implicit def identifiableTuple[K1, K2](
      implicit
      a: Identifiable[K1],
      b: Identifiable[K2]
  ): Identifiable.Aux[(K1, K2), (a.K, b.K)] = new Identifiable[(K1, K2)] {
    type K = (a.K, b.K)
    override def identify(id: (K1, K2)): K = {
      val k1 = a.identify(id._1)
      val k2 = b.identify(id._2)
      (k1, k2)
    }
  }

However, when I try to use it like bellow the implicit parameters is not resolved

def a[K: Identifiable](key:K) = { 
case k => 
 val keyString: String = the[Identifiable.Aux[K, String]].identify(key) 
case (k1,k2) => 
 val keyString: (String,String) = the[Identifiable.Aux[K, (String, String)]].identify(key) }


Solution

  • You demand implicit with path-dependent type in type constraint but then you summon implicit with that type fixed to something.

    For that to work compiler would have to be able to prove that dependent type in Identifiable is equal to K which in current code it cannot do.

    You can try:

    • use the same convention in both places (either both with Aux or both with dependent type)
    • prove that the dependent type is equal to K with implicit evidence ev: identifiable.K =:= K