2

这是一个奇怪的情况:

如果我注释掉feed_usingExplicitTypeClassInstance下面的调用,那么我会收到编译器错误。

非常令人费解。有什么解释吗?

我的意思是,我注释掉一个函数调用(它不返回任何值),然后代码不再编译?

这在理论上应该是可能的吗?在任何编程语言中?

我的意思是我注释掉类似println("hello")的东西然后代码不再编译了?

当然,如果我注释掉声明之类的东西是可以理解的,但是调用一个不返回任何东西的函数?

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")
}

这是错误:

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)

编辑:

如果我插入该行:

AnimalTypeClass.CatInstance

前:

feed_usingImplicitTypeClassInstance(new CatFood)

然后代码再次编译,即使该行

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

被注释掉了。

4

2 回答 2

7

This is a pretty well known issue, where implicits which appear after their usage in the same file and without an explicit type annotation are not found. For that reason it is strongly advised (and this will eventually be enforced) to give all non-local implicits an explicit type annotation. Unfortunately implicit objects are a bit tricky here, because they always act like implicit definitions without type annotation, and it is impossible to give them an explicit type... However last I checked this seemed to be fixed in Dotty for implicit objects.

See also, among others https://github.com/scala/bug/issues/8697

The reason that it does work when you uncomment a call to AnimalTypeClass.CatInstance in your code is that that reference will force the implicit object to be type checked earlier, so its type will be known before its implicit usage.

于 2018-04-29T20:15:41.013 回答
5

使用此值后,您在同一文件中定义了隐式值。当您调用feed_usingImplicitTypeClassInstance. feed_usingExplicitTypeClassInstance使用对此隐式值的显式引用进行调用会强制对隐式进行初始化,并且编译器可以在隐式调用中使用它。

可能的解决方案:

  • 将隐式值的定义移动到另一个文件。
  • 如果隐式值在同一个文件中,请将其定义移到您隐式使用它的位置上方。
于 2018-04-29T20:04:11.667 回答