В нерасширенном Haskell объявление
data A = B
определяет два новых объекта, по одному на уровне вычислений и типов:
- На уровне типов новый базовый типс именем
A
(типа *
) и - На уровне вычислений создается новое базовое вычисление с именем
B
(типа A
).
КогдаВы включаете DataKinds
, объявление
data A = B
теперь определяет четыре новых объекта, один на уровне вычислений, два на уровне типов и один на уровне типов:
- На уровне вида новый базовый тип
A
, - На уровне типа новый базовый тип
'B
(типа A
), - На типеуровень, новый базовый тип
A
(типа *
) и - На уровне вычислений новый базовый тип
B
(типа A
).
Это строгий расширенный набор того, что у нас было раньше: старый (1) теперь (3), а старый (2) теперь (4).
Эти новые сущности объясняют следующие взаимодействияты описал:
:type Zero
Zero :: Nat
:kind 'Zero
'Zero :: Nat
:type 'Zero
Syntax error on 'Zero
Я думаю, понятно, как это объясняет первые два.Последнее объясняется потому, что 'Zero
- это вещь уровня типа - вы не можете запрашивать тип типа, только тип вычисления!
Теперь, в Haskell, везде, гдеимя встречается, из окружающего синтаксиса ясно, предназначено ли это имя как имя уровня вычислений, имя уровня типа или имя уровня рода.По этой причине несколько раздражает необходимость включать отметку в 'B
на уровне типа - в конце концов, компилятор знает , что мы на уровне типа и поэтому не можемссылаясь на неподнятый уровень вычислений B
.Поэтому для удобства вам разрешено снимать галочку, когда это однозначно.
С этого момента я буду различать «бэкэнд» - там, где есть только четыре сущности, описанные выше, и которыевсегда однозначны - и «поверхностный синтаксис», который представляет собой материал, который вы вводите в файл и передаете в GHC, который содержит неоднозначность, но более удобен.Используя эту терминологию, в поверхностном синтаксисе можно написать следующие вещи со следующими значениями:
Surface syntax Level Back end
Name computation Name
Name type Name if that exists; 'Name otherwise
'Name type 'Name
Name kind Name
---- all other combinations ---- error
Это объясняет ваше первое взаимодействие (и единственное, которое осталось необъясненным выше):
:kind Zero
Zero :: Nat
Поскольку :kind
должен применяться к объекту на уровне типа, компилятор знает, что имя синтаксиса поверхности Zero
должно быть на уровне типа.Поскольку нет никакого имени конца уровня Zero
, вместо этого он пытается 'Zero
и получает удар.
Как это может быть неоднозначным?Обратите внимание, что мы определили две новых сущности на уровне типа с одной декларацией.Для простоты введения я назвал новые объекты в левой и правой части уравнения разными вещами.Но давайте посмотрим, что произойдет, если мы просто слегка изменим объявление:
data A = A
Мы по-прежнему вводим четыре новых серверных объекта:
- Kind
A
, - Тип
'A
(типа A
), - Тип
A
(типа *
) и - Вычисление
A
(типа A
).
Упс!Теперь есть и 'A
и A
на уровне типа.Если вы уберете отметку в синтаксисе поверхности, она будет использовать (3), а не (2) - и вы можете явно выбрать (2) с синтаксисом поверхности 'A
.
Более тогоэто не должно происходить все из одной декларации.Одна декларация может производить помеченную версию, а другая - не отмеченную версию;например,
data A = B
data C = A
представит имя конца уровня типа A
из первого объявления и имя конца уровня 'A
из второго объявления.