Давайте упростим:
Inductive MyTy : Set -> Type :=
MkMyTy : forall (A : Set), A -> MyTy A.
Definition extract (m : MyTy nat) : nat :=
match m with MkMyTy _ x => S x end.
Это не удалось:
The term "x" has type "S" while it is expected to have type "nat".
ваты.
Это потому что я сказал
Inductive MyTy : Set -> Type
Это сделал первый аргумент MyTy
индексом MyTy
, в отличие от параметра. Индуктивный тип с параметром может выглядеть так:
Inductive list (A : Type) : Type :=
| nil : list A
| cons : A -> list A -> list A.
Параметры именуются слева от :
и не являются forall
-d в определении каждого конструктора. (Они по-прежнему присутствуют в типах конструкторов вне определения: cons : forall (A : Type), A -> list A -> list A
.) Если я сделаю Set
параметром MyTy
, то можно определить extract
:
Inductive MyTy (A : Set) : Type :=
MkMyTy : A -> MyTy A.
Definition extract (m : MyTy nat) : nat :=
match m with MkMyTy _ x => S x end.
Причина этого в том, что внутри match
игнорирует все, что вы знаете об индексах проверяемого извне. (Или, скорее, базовое выражение match
в Gallina игнорирует индексы. Когда вы пишете match
в исходном коде, Coq пытается преобразовать его в примитивную форму, в то же время включая информацию из индексов, но это часто не удается. ) То, что m : MyTy nat
в первой версии extract
просто не имело значения. Вместо этого совпадение дало мне S : Set
(имя было автоматически выбрано Coq) и x : S
, согласно конструктору MkMyTy
, без упоминания nat
. Между тем, поскольку у MyTy
есть параметр во второй версии, я на самом деле получаю x : nat
. На этот раз _
действительно заполнитель; его обязательно нужно записать как _
, потому что нечего сопоставлять, и вы можете Set Asymmetric Patterns
, чтобы он исчез.
Причина, по которой мы различаем параметры и индексы, заключается в том, что параметры имеют множество ограничений - особенно, если I
является индуктивным типом с параметрами, тогда параметры должны появляться как переменные в типе возврата каждого конструктора:
Inductive F (A : Set) : Set := MkF : list A -> F (list A).
(* ^--------^ BAD: must appear as F A *)
В вашей задаче мы должны указать параметры там, где можем. Например. бит match wr with Wrap Y w => _ end
неверен, поскольку аргумент XY
для Wrapper
является индексом, поэтому тот факт, что wr : Wrapper Y
игнорируется; вам также нужно будет заняться делом Wrap X w
. Coq не удосужился сказать вам это.
Inductive Wrapped (ab : AB) : XY -> Set :=
| W : forall (xy : XY), Wrapped ab xy
| WW : Wrapped ab (match ab with A => X | B => Y end).
Inductive Wrapper (xy : XY) : Set := WrapW : Wrapped A xy -> Wrapper xy.
А теперь ваш test
компилирует (почти):
Definition test (wr : Wrapper Y): nat :=
match wr with
| WrapW _ w => (* mandatory _ *)
match w with
| W _ Y => 27 (* mandatory _ *)
end
end.
, поскольку наличие параметров дает Coq достаточно информации для его match
-разработки, чтобы использовать информацию из индекса Wrapped
. Если вы введете Print test.
, вы увидите, что есть небольшой скачок для передачи информации об индексе Y
через примитив match
s, который в противном случае игнорировал бы его. См. Справочное руководство для получения дополнительной информации.