Я работаю над формализацией свободных селективных аппликативных функторов в Coq, но борюсь с доказательствами по индукции для индуктивных типов данных с неоднородными параметрами типа.
Позвольте мне дать немноговведения в тип данных, с которым я имею дело.В Haskell мы кодируем свободные селективные функторы как GADT:
data Select f a where
Pure :: a -> Select f a
Select :: Select f (Either a b) -> f (a -> b) -> Select f b
Важнейшей вещью здесь является переменная экзистенциального типа b
во втором конструкторе данных.
Мы можем перевести это определениеto Coq:
Inductive Select (F : Type -> Type) (A : Set) : Set :=
Pure : A -> Select F A
| MkSelect : forall (B : Set), Select F (B + A) -> F (B -> A) -> Select F A.
В качестве примечания я использую опцию -impredicative-set
для его кодирования.
Coq генерирует следующий принцип индукции для этого типа данных:
Select_ind :
forall (F : Type -> Type) (P : forall A : Set, Select F A -> Prop),
(forall (A : Set) (a : A), P A (Pure a)) ->
(forall (A B : Set) (s : Select F (B + A)), P (B + A)%type s ->
forall f0 : F (B -> A), P A (MkSelect s f0)) ->
forall (A : Set) (s : Select F A), P A s
Здесь интересным является предикат P : forall A : Set, Select F A -> Prop
, который параметризуется не только в выражении, но и в параметре типа выражения.Как я понимаю, принцип индукции имеет эту конкретную форму из-за первого аргумента конструктора MkSelect
типа Select F (B + A)
.
Теперь я хотел бы доказать утверждения, подобные третьему Прикладному закону для определенноготип данных:
Theorem Select_Applicative_law3
`{FunctorLaws F} :
forall (A B : Set) (u : Select F (A -> B)) (y : A),
u <*> pure y = pure (fun f => f y) <*> u.
Которые содержат значения типа Select F (A -> B)
, то есть выражения, содержащие функции.Однако вызов induction
для переменных таких типов приводит к неправильному типу терминов.Рассмотрим упрощенный пример равенства, которое может быть тривиально доказано с помощью reflexivity
, но не может быть доказано с помощью induction
:
Lemma Select_induction_fail `{Functor F} :
forall (A B : Set) (a : A) (x : Select F (A -> B)),
Select_map (fun f => f a) x = Select_map (fun f => f a) x.
Proof.
induction x.
Coq жалуется на ошибку:
Error: Abstracting over the terms "P" and "x" leads to a term
fun (P0 : Set) (x0 : Select F P0) =>
Select_map (fun f : P0 => f a) x0 = Select_map (fun f : P0 => f a) x0
which is ill-typed.
Reason is: Illegal application (Non-functional construction):
The expression "f" of type "P0" cannot be applied to the term
"a" : "A"
Здесь Coq не может создать предикат, абстрагированный от переменной типа, потому что приложение с обратными функциями из оператора становится не типизированным.
Мой вопрос: как мне использовать индукцию для моего типа данных?Я не вижу способа, как изменить принцип индукции таким образом, чтобы предикат не абстрагировал тип.Я пытался использовать dependent induction
, но он выдвигал индуктивную гипотезу, ограниченную равенствами, подобными (A -> B -> C) = (X + (A -> B -> C))
, которые, я думаю, было бы невозможно создать.
Пожалуйста, посмотрите полный пример на GitHub: https://github.com/tuura/selective-theory-coq/blob/impredicative-set/src/Control/Selective/RigidImpredSetMinimal.v