Странная ошибка компилятора Scala при удалении вызова функции с возвращаемым типом Unit, как это вообще возможно? - PullRequest
0 голосов
/ 29 апреля 2018

Вот странная ситуация:

Если я закомментирую вызов 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)

EDIT:

Если я вставлю строку:

AnimalTypeClass.CatInstance

перед:

feed_usingImplicitTypeClassInstance(new CatFood)

затем код компилируется снова, даже если строка

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

закомментировано.

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Это довольно известная проблема, когда не обнаруживаются следствия, которые появляются после их использования в том же файле и без явной аннотации типа . По этой причине настоятельно рекомендуется (и это в конечном итоге будет применяться) дать всем нелокальным последствиям явную аннотацию типа. К сожалению, неявные объекты здесь немного сложны, потому что они всегда действуют как неявные определения без аннотации типа, и невозможно дать им явный тип ... Однако в последний раз я проверял, что это было исправлено в Dotty для неявных объектов.

См. Также, среди прочего https://github.com/scala/bug/issues/8697

Причина, по которой он работает, когда вы раскомментируете вызов AnimalTypeClass.CatInstance в своем коде, заключается в том, что эта ссылка заставит неявный объект проверяться на тип ранее, поэтому его тип будет известен до его неявного использования.

0 голосов
/ 29 апреля 2018

У вас есть определение неявного значения в том же файле после использования этого значения. Он не инициализируется, когда компилятор ищет неявное значение при вызове feed_usingImplicitTypeClassInstance. Вызов feed_usingExplicitTypeClassInstance с явной ссылкой на это неявное значение заставляет неявное инициализироваться, и компилятор может использовать его в неявном вызове.

Возможные решения:

  • Переместить определение неявного значения в другой файл.
  • Если неявное значение находится в том же файле, поместите его определение над тем местом, где вы его неявно используете.
...