2015-12-07 3 views
3

У меня есть некоторые проблемы с выводом типа Scala. В следующем примере рабочего листа я определил карту, которая сопоставляет любые значения функции, возвращающей значение Единицы.Непонятный вывод типа в scala

Интересно, что когда я пытаюсь определить одну и ту же карту, используя только одну строку кода, она не работает, потому что функции «bar» return-type внезапно меняются на Any вместо Unit.

type UnitFun = (Any) => Unit 

val foo = "foo" 
val bar = (a: Any) => System.out.println("bar") 

val map: Map[Any, UnitFun] = Map().withDefaultValue(((a: Any) => Unit)) 
val doesCompile: Map[Any, UnitFun] = map + (foo -> bar) 

val doesNotCompile: Map[Any, UnitFun] = Map().withDefaultValue(((a: Any) => Unit)) + (foo -> bar) 

Я использую IDEA14 в IDE с Scala 2.11.6

Мне кажется, как это особенность/ошибка компилятора Scala, или я что-то отсутствует?

Кстати, я только что заметил, что когда я использую «бар» в качестве значения по умолчанию в «» doesNotCompile так:

val doesCompileNow: Map[Any, UnitFun] = Map().withDefaultValue(bar) + (foo -> bar) 

вдруг, кажется, работает, я очень озадачены прямо сейчас. : D

Edit 1: @Mikolak

В этом случае, как же следующий код работает? :)

val a: Any => Unit = (a: Any) => Unit 
val b: Any => Unit = (a: Any) =>() 

Не должны ли оба выражения быть другого типа? Или существует какое-то неявное преобразование типов?

+0

Добавлено объяснение относительно вашего редактирования. Обратите внимание, что это явление, полностью ортогональное исходному. –

+0

Уже видел это, я думаю, что неявное преобразование из ** Unit.type ** в ** Any ** (в соответствии с intellij output) является тем, что привело меня к следующему этапу. Я предполагаю, что это просто очередное некое обращение. :) – pmkrefeld

+0

Одна вещь для добавления: ** не верю ** Проверка синтаксиса IntelliJ. При медленном улучшении он все еще имеет склонность выводить как ложные срабатывания, так и ложные негативы. Другими словами, ваш первый курс действий при появлении странной ошибки должен заключаться в запуске 'sbt compile'. –

ответ

8

Оригинал компиляции ошибка

Ошибка компиляции происходит потому, что эта функция:

(a: Any) => Unit 

имеет тип

Any => Unit.type 

и не типа:

Any => Unit 

Другими словами, вы возвращаете Unit, компаньон объекта Unit типа. Этот объект-компаньон имеет тип Unit.type, который представляет собой тип, чем Unit (это относится ко всем сопутствующим объектам в Scala).

Что нужно, так это фактически вернуть значение типа Unit. As outlined in the docs, единственным значением является ().

Итак, ваша функция по умолчанию должна быть: (a: Any) =>().


EDIT: Что касается дополнительного вопроса.

преобразования в Отдел

Здесь:

val a: Any => Unit = (a: Any) => Unit 

вы явно вводить выражение иметь тип возвращаемого Unit. Обычно это приведет к ошибке типа, но (как вы подозреваете) «к счастью» вы вызвали one of the pre-defined implicit value conversions, а именно:

Значение отбрасывая

Если е имеет некоторый тип значения и ожидаемый тип блока , e преобразуется в ожидаемый тип, вставляя его в член {e;()}.

Таким образом, это:

(a: Any) => Unit //return type is Unit.type 

становится:

(a: Any) => {Unit;();} //return type is Unit 

Обратите внимание, что в соответствии с определением, преобразование применяется к любому значению, так что, например, val c: Unit = "c" дает тот же результат.

Смежные вопросы