奇怪的Scala编译器错误,当删除对具有单元返回类型的函数的调用时,这怎么可能呢?
这里有一个奇怪的情况: 如果我使用下面的xplicittypeclassinstance注释掉对奇怪的Scala编译器错误,当删除对具有单元返回类型的函数的调用时,这怎么可能呢?,scala,dependent-type,scala-implicits,Scala,Dependent Type,Scala Implicits,这里有一个奇怪的情况: 如果我使用下面的xplicittypeclassinstance注释掉对提要的调用,那么我会得到一个编译器错误 非常令人费解有什么解释吗? 我的意思是,我注释掉一个函数调用(它不返回值),然后代码就不再编译了 这在理论上是否可能?在任何编程语言中 我的意思是我注释掉了类似于println(“hello”)的东西,然后代码就不再编译了 当然,如果我注释掉一个声明或其他东西,但是调用一个不返回任何内容的函数,这是可以理解的 object AnimalFeeder extend
提要的调用,那么我会得到一个编译器错误
非常令人费解有什么解释吗?
我的意思是,我注释掉一个函数调用(它不返回值),然后代码就不再编译了
这在理论上是否可能?在任何编程语言中
我的意思是我注释掉了类似于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")
}
编辑:
如果我插入该行:
AnimalTypeClass.CatInstance
之前:
feed_usingImplicitTypeClassInstance(new CatFood)
然后代码再次编译,即使行
feed_usingExplicitTypeClassInstance(AnimalTypeClass.CatInstance)(new CatFood())
注释掉。使用该值后,在同一文件中有隐式值的定义。当您使用ImplicitTypeClassInstance调用提要时,当编译器查找隐式值时,它不会初始化。通过显式引用此隐式值调用feed\u usingExplicitTypeClassInstance
,将强制隐式初始化,编译器可以在隐式调用中使用它
可能的解决办法:
- 将隐式值的定义移动到另一个文件
- 如果隐式值位于同一文件中,请将其定义移到隐式使用它的位置上方
这是一个众所周知的问题,在同一文件中使用隐式元素之后,如果没有显式类型注释,则找不到隐式元素。因此,强烈建议(最终将强制执行)为所有非局部隐式提供显式类型注释。不幸的是,隐式对象在这里有点棘手,因为它们总是像没有类型注释的隐式定义一样工作,并且不可能给它们一个显式类型。。。然而,上一次检查时,对于隐式对象,这似乎在Dotty中得到了修复
除其他外,另见
当您在代码中取消对AnimalTypeClass.CatInstance
调用的注释时,它确实起作用的原因是该引用将强制隐式对象更早地进行类型检查,因此在隐式使用之前就知道其类型。非常感谢您的回答,我现在要睡觉了,明天当我的大脑重新开始工作的时候,试着去理解它。再次感谢你的回答,所以当你说,“它的类型在它的隐含用法之前就会被知道”你这是什么意思?谁知道?编译器?那么编译器会知道它正在寻找的“类型”存在吗?或者存在该类型的隐式对象?还是类型本身?“要进行类型检查的隐式对象”是什么意思?这是否意味着编译器将一个类型与隐式对象(一个带有名称的值)关联(推断),并且当这种情况发生时,它会将隐式对象添加到它用来解析隐式对象的字典中?为了让编译器知道某个隐式对象是否符合条件,它需要知道它的类型。当定义没有类型注释时,编译器将必须处理该定义的整个主体以推断其类型。但是编译器无法在开始第一次隐式搜索之前推断所有类型,因为隐式也会影响类型推断。显然,这可能会导致推理机出现一些循环行为。但是,当您显式引用该定义时,编译器必须更早地推断其类型,以便键入使用它的当前表达式。Hmmm,因此“编译器无法在开始第一次隐式搜索之前推断所有类型”是所有这些和“当您显式引用该定义时,编译器必须更早地推断其类型,以便在使用它的地方键入当前表达式”表示编译器“知道”“隐式的类型是什么,然后它就有资格在可以使用的地方使用。非常感谢,这是一个很好的评论,解释了这种情况。非常感谢你的回答,我也是科尔玛,我现在要睡觉了,明天当我的大脑重新开始工作时试着去理解它。你的显式函数调用导致AnimalTypeClass
对象被实例化,从而创建隐式CatInstance
。注释掉该代码后,AnimalTypeClass
不再实例化,因此范围中不再有隐式AnimalTypeClass
,因此出现错误。函数调用本身是不相关的。
feed_usingExplicitTypeClassInstance(AnimalTypeClass.CatInstance)(new CatFood())