У меня нет 100% полного ответа, но у меня есть указатель, который может быть достаточным для вас.
Компилятор Scala работает с GADT (обобщенными алгебраическими типами данных) очень специфическим образом. Некоторые случаи решаются с особой обработкой, некоторые случаи не решены. Дотти пытается заполнить большую часть дыр, и она уже решила множество связанных с этим проблем, однако есть еще немало открытых .
Типичный пример специальной обработки GADT в компиляторе Scala 2 очень связан с вашим вариантом использования. Если мы посмотрим на:
def method[A](arg: Base[A]) = {
arg match {
case Derived(_) => 42
}
}
и мы явно объявляем тип возвращаемого значения A
:
def method[A](arg: Base[A]): A
это будет компилироваться просто отлично. Ваша IDE может жаловаться, но компилятор пропустит это. Метод говорит, что возвращает A
, но случай сопоставления с шаблоном оценивается в Int
, который теоретически не должен компилироваться. Тем не менее, специальная обработка GADT в компиляторе говорит, что это нормально, потому что в этой конкретной ветке сопоставления с образцом A
была «исправлена», чтобы быть Int
(потому что мы сравнили с Derived
которой есть a Base[Int]
).
Параметр общего типа для GADT (в нашем случае A
) должен быть где-то объявлен. И вот интересная часть - специальная обработка компилятора работает только тогда, когда она объявлена как параметр типа метода включения . Если он исходит из члена типа или параметра типа включающей черты / класса, он не компилируется, как вы сами убедились.
Вот почему я сказал, что это не на 100% полный ответ - я не могу указать конкретное место (например, официальную спецификацию), которое документирует это должным образом. Источники по обработке GADTs в Scala сводятся к паре из · блоги , · , которые являются большими по пути, но если вы хотите больше , чем вам придется копаться в коде компилятор самостоятельно. Я попытался сделать именно это, и я думаю, что это сводится к этому методу , но если вы действительно хотите пойти глубже, вы можете захотеть пинговать кого-то более опытного с кодовой базой компилятора Scala.