scaladependent-typescala-implicits

Strange Scala compiler error when removing a call to a function that has Unit return type, how is this even possible?


Here is a strange situation:

If I comment out the call to feed_usingExplicitTypeClassInstance below, then I get a compiler error.

Very puzzling. Any explanation ?

I mean, I comment out a function call (which returns no value) and then the code does not compile anymore ?

Should this be even possible at all in theory ? In any programming language ?

I mean I comment out something like println("hello") and then the code does not compile anymore ?

Of course it would be understandable if I would comment out a declaration or something, but a call to a function that does not return anything ?

object AnimalFeeder extends App {

  def feed_usingExplicitTypeClassInstance[AnimalInstance]
    (animalTypeClass: AnimalTypeClass[AnimalInstance])
    (food: animalTypeClass.FoodThatAnimalLikes) =
      {
          animalTypeClass.feed(food)
      }

  def feed_usingImplicitTypeClassInstance[AnimalInstance, Food]
    (food: Food)
    (implicit animalTypeClass: AnimalTypeClass.Aux[Food,AnimalInstance]) =
      {
        animalTypeClass.feed(food)
      }


  // If I comment out this line, THEN !, I get an error !!!! How ???
  feed_usingExplicitTypeClassInstance(AnimalTypeClass.CatInstance)(new CatFood())



  feed_usingImplicitTypeClassInstance(new CatFood)

}



trait Food {
  def eat(): Unit
}



trait AnimalTypeClass[AnimalInstance] {
  type FoodThatAnimalLikes <: Food
  def feed(f: FoodThatAnimalLikes) = f.eat()
}



object AnimalTypeClass {

  type Aux[Food, Animal] = AnimalTypeClass[Animal] {
    type FoodThatAnimalLikes = Food
  }

  implicit object CatInstance extends AnimalTypeClass[Cat] {
    override type FoodThatAnimalLikes = CatFood
  }

}


trait Cat

class CatFood extends Food {
  override def eat(): Unit = println("meow")
}

This is the error:

Error:(23, 38) could not find implicit value for parameter animalTypeClass: AnimalTypeClass.Aux[CatFood,AnimalInstance]
  feed_usingImplicitTypeClassInstance(new CatFood)

Error:(23, 38) not enough arguments for method feed_usingImplicitTypeClassInstance: (implicit animalTypeClass: AnimalTypeClass.Aux[CatFood,AnimalInstance])Unit.
Unspecified value parameter animalTypeClass.
  feed_usingImplicitTypeClassInstance(new CatFood)

EDIT:

If I insert the line:

AnimalTypeClass.CatInstance

before:

feed_usingImplicitTypeClassInstance(new CatFood)

then the code compiles again, even if the line

feed_usingExplicitTypeClassInstance(AnimalTypeClass.CatInstance)(new CatFood())

is commented out.


Solution

  • You have the definition of the implicit value in the same file after the usage of this value. It is not initialized when the compiler looks for an implicit value when you call feed_usingImplicitTypeClassInstance. Calling feed_usingExplicitTypeClassInstance with an explicit reference to this implicit value forces the implicit to initialize, and the compiler can use it in the implicit call.

    Possible solutions: