Как Дотти решает, как вывести/когда расширить типы союзов?

Расширение типов союзов обсуждалось здесь, но мне кажется, что найти ответ на следующий случай

Начнем со следующего

val x = List(1, 2, "a")

Этот разнородный список выводится как List[Any] Так же, как в Scala 2.

Однако следующее

val x2 = List(List(1, 2), Vector("a", "b"))

выводится как List[scala.collection.immutable.AbstractSeq[Int | String]]

Это довольно запутанное поведение. Почему LUB двух непересекающихся типов в одном случае выводится как Any, а в другом - как тип объединения?

Если это просто дизайнерское решение, есть ли такие случаи, о которых следует знать?


person sinanspd    schedule 16.09.2020    source источник


Ответы (1)


умнее

мы избегаем вывода типов объединения по той же причине, по которой мы избегаем вывода одноэлементных типов, потому что иногда они слишком точны

Моя интерпретация этого утверждения состоит в том, что более разумно вводить List(1,2) как List[Int] вместо List[1 | 2], или List(new Cat, new Dog) как List[Animal] вместо List[Cat | Dog].

См. также комментарий Дмитрия из соответствующего вопроса (мой )

Цитата из guillaume.martres.me/talks/dotty-tutorial/#/1 /13 (слайд 15 Вывод типов и типы объединения): По умолчанию Dotty не выводит типы объединения, они аппроксимируются супертипом, не являющимся объединением. Типы союзов могут быть слишком точными и препятствовать компиляции легитимного кода.

Также см. упоминание на 23:38 выступления Дотти и типы: история на данный момент.

Однако расширение объединения выполняется один раз, чтобы избежать бесконечного LUB согласно умнее< /а>:

когда мы делаем расширение один раз, результирующий тип может иметь где-то объединение (например, пример в разделе Join of a union type в документе), мы не будем расширять это, если сделаем сделать расширение рекурсивно, мы действительно могли бы получить бесконечный lub

person Mario Galic    schedule 16.09.2020
comment
Я видел этот комментарий и видео, но, если честно, он не совсем ответил на мой вопрос. Я думаю, что у меня есть некоторое понимание того, почему они приняли решение не выводить типы объединения, но мне все еще не ясно, почему в вашем примере List[Box[Square | Circle]] выводится как объединение? Если вывести типы объединения сложно, то почему в данном случае это не было сложно? Я что-то пропустил в комментариях или видео? - person sinanspd; 17.09.2020
comment
@sinanspd Кажется, расширение объединения выполняется только один раз, чтобы избежать бесконечного lub в соответствии с умнее : если бы мы сделали рекурсивное расширение, мы действительно могли бы получить бесконечный lub См. также Соединение типа объединения - person Mario Galic; 17.09.2020
comment
Спасибо Марио! Я думал, что бесконечный lub был предотвращен типами пересечения, но я думаю, что в этой истории есть нечто большее. Можете ли вы комментарий Гийома в ответ, чтобы я мог принять это? Я думаю, что это самый прямой ответ на этот вопрос - person sinanspd; 17.09.2020