У мене немає 100% повної відповіді, але у мене є вказівник, який може бути достатнім для вас.
Компілятор Scala дуже конкретно стосується GADT (Узагальнені типи алгебраїчних даних). Деякі справи вирішуються спеціальним поводженням, деякі випадки - невирішеними. Dotty намагається заповнити більшість лунок, і це вже вирішило багато пов'язаних з цим питань, однак є ще досить багато відкритих .
Типовий приклад спеціального поводження з GADT у компіляторі Scala 2 дуже пов'язаний із вашим випадком використання. Якщо ми подивимось на:
def method[A](arg: Base[A]) = {
arg match {
case Derived(_) => 42
}
}
і ми явно оголошуємо тип повернення таким A
:
def method[A](arg: Base[A]): A
вона складеться чудово. Ваш IDE може скаржитися, але компілятор відпустить це. Метод каже, що він повертає A
, але випадок відповідності шаблону обчислюється в an Int
, який теоретично не слід компілювати. Однак, спеціальна обробка GADT в компіляторі говорить, що це добре, тому що в цій конкретній гілці відповідності шаблону A
було "зафіксовано", щоб бути Int
(тому що ми відповідали, на Derived
якому це а Base[Int]
).
Параметр загального типу для GADT (у нашому випадку A
) повинен десь бути оголошений. І ось цікава частина - спеціальний обробник компілятора працює лише тоді, коли він оголошений як параметр типу методу укладання . Якщо він надходить від типу типу або параметру типу додаючої ознаки / класу, він не компілюється, як ви свідчили самі.
Ось чому я сказав, що це не 100% повна відповідь - я не можу вказати на конкретне місце (наприклад, офіційну специфікацію), яке це правильно документує. Джерела по обробці GADTs в Scala зводяться до парі з · блоги , · , які є великими по шляху, але якщо ви хочете більше , ніж вам доведеться копатися в коді компілятор самостійно. Я спробував зробити саме це, і я думаю, що це зводиться до цього методу , але якщо ви дійсно хочете заглибитись, ви, можливо, захочете пінговувати когось більш досвідченого з кодовою базою компілятора Scala.