Edmondo
Edmondo

Reputation: 20080

Scala inference on higher kinded types versus evidences

I am trying to provide some typeclasses implementations which involves higher kinded types, as in the following code:

trait Blah[A,B] {
  def apply(b:B):List[A]
}

object Blah {
  implicit def blah1[A,B<:List[A]]:Blah[A,B] = new Blah[A,B]{
    def apply(b:B):List[A] = b
  }

  implicit def blah2[A,B](implicit ev: B<:<List[A]):Blah[A,B] = new Blah[A,B]{
    def apply(b:B):List[A] = b
  }
}

object Stuff {

  def method[A,B](b:B)(implicit blah:Blah[A,B]):List[A] = {
    blah(b)
  }

  method(List(2,3))
}

If I remove the method Blah.blah2 , the compiler fails because it can't resolve an implicit. Why does the second form (using an implicit evidence) works instead, and when it should be used?

Upvotes: 1

Views: 59

Answers (1)

sarveshseri
sarveshseri

Reputation: 13985

Well... its because it is not able to infer correct types as the first implicit blah1 expects a relation between A and B.

scala> :pa
// Entering paste mode (ctrl-D to finish)

trait Blah[A,B] {
  def apply(b:B):List[A]
}

object Blah {
  implicit def blah1[A,B<:List[A]]:Blah[A,B] = new Blah[A,B] {
    def apply(b:B):List[A] = b
  }
}

def method[A,B](b:B)(implicit blah:Blah[A,B]):List[A] = {
  blah(b)
}

// Exiting paste mode, now interpreting.

defined trait Blah
defined object Blah

method: [A, B](b: B)(implicit blah: Blah[A,B])List[A]

scala> method( List( 4, 5) )
<console>:37: error: could not find implicit value for parameter blah: Blah[A,List[Int]]
              method( List( 4, 5) )
                    ^

See... its looking for implicit of type Blah[ A, List[ Int ] ]

We just need to help it with types and it will work,

scala> method[ Int, List[ Int] ]( List( 3, 4, 5 ) )
res1: List[Int] = List(3, 4, 5)

Upvotes: 1

Related Questions