Трудности Coq в определении конструкторов с использованием принудительных типов - PullRequest
1 голос
/ 25 февраля 2020

Определения

Я работаю над формализацией типичного лямбда-исчисления в Coq, и чтобы сохранить нотацию управляемой, я стал полагаться на принуждения. Однако я столкнулся с некоторыми трудностями, которые кажутся странными.

Сейчас я пытаюсь работать со следующими типами:

  • type: дескриптор допустимого типа на языке (например, функция, Unit, et c ...)
  • var: тип переменной, определяемый как nat
  • VarSets: набор переменных
  • суждение : пара var / my_type
  • ty_ctx: списки суждений.
  • ctx_join: пары описывающих ty_ctx непересекающихся наборов переменных

Фактические определения приведены ниже , за исключением ctx_join, который дается в следующем блоке

(* Imports *)
Require Import lang_spec.
From Coq Require Import MSets.
Require Import List.
Import ListNotations.

Module VarSet := Make(Nat_as_OT).

Inductive Judgement : Type :=
| judge (v : var) (t : type)
.

Definition ty_ctx := (list Judgement).

Definition disj_vars (s1 s2 : VarSet.t) := VarSet.Empty (VarSet.inter s1 s2).

Часто я хотел бы сделать такие выражения, как "этот var не появляется в наборе переменных, связанных с ty_ctx", и с этой целью я Вы установили несколько типов принуждения между этими типами ниже.


(* Functions to convert between the different types listed above *)

Fixpoint var_to_varset (v : var) : VarSet.t :=
  VarSet.singleton v.
Coercion var_to_varset : var >-> VarSet.t.

Fixpoint bound_variables (g : ty_ctx) : VarSet.t :=
  match g with
  | nil => VarSet.empty
  | cons (judge v _) g' =>VarSet.union (VarSet.singleton v) (bound_variables g')
  end.
Coercion bound_variables : ty_ctx >-> VarSet.t.

Inductive ctx_join :=
| join_single (g : ty_ctx)
| join_double (g1 g2 : ty_ctx)
              (disjoint_proof : disj_vars g1 g2)
.

Fixpoint coerce_ctx_join (dj : ctx_join) : ty_ctx :=
  match dj with
  | join_single g => g
  | join_double g1 g2 _ => g1 ++ g2
  end.
Coercion coerce_ctx_join : ctx_join >-> ty_ctx.

Fixpoint coerce_judgement_to_ty_ctx (j : Judgement) : ty_ctx :=
  cons j nil.
Coercion coerce_judgement_to_ty_ctx : Judgement >-> ty_ctx.


Вы заметите, что определение ctx_join основано на приведении аргументов от ty_ctx к VarSet.

Я составил иерархию конверсий, чтобы прояснить ситуацию * 10 32 *enter image description here

Проблема

Я бы хотел определить индуктивный тип с помощью следующего конструктора

Inductive expr_has_type : ty_ctx -> nat -> type -> Prop :=
(* General Expressions *)
| ty_var (g : ty_ctx) (x : var) (t : type) (xfree : disj_vars x g)
  : expr_has_type (join_double (judge x t) g xfree) x t
.

Проблема в том, что когда я это делаю, я получаю следующую ошибку:

Error:
In environment
expr_has_type : ty_ctx -> nat -> type -> Prop
g : ty_ctx
x : var
t : type
xfree : disj_vars x g
The term "xfree" has type "disj_vars x g" while it is expected to have type
 "disj_vars (judge x t) g" (cannot unify "VarSet.In a (VarSet.inter (judge x t) g)" and
"VarSet.In a (VarSet.inter x g)").

Однако, если я изменяю тип xfree на disj_vars (VarSet.singleton x) g, тогда определение работает отлично! Это кажется очень странным, поскольку disj_vars определяется только на VarSet с, и поэтому кажется, что x следует автоматически преобразовать в VarSet.singleton x, поскольку именно так настроено приведение.

Четный более странным является тот факт, что если я не настроил приведение от vars к varsets, то Coq правильно жалуется на применение dis_vars к var вместо VarSet. Таким образом, принуждение определенно делает что-то

Может кто-нибудь объяснить мне, почему первое определение не удается? Учитывая приведенные мною меры принуждения, мне, как и всем приведенным выше определениям, должно быть эквивалентно

Примечание

Изменение типа xfree на disj_vars (judge x t) g также исправляет ошибку. Это тоже кажется странным, так как для применения disj_vars к j := (judge x t) сначала его нужно привести к ty_ctx через cons j nil, затем к VarSet через bound_variables, что должно привести к VarSet содержит только x (что эквивалентно VarSet.singleton x?). Так что эта цепочка принуждения, кажется, go отключается без помех, в то время как другая выходит из строя, хотя она проще

1 Ответ

1 голос
/ 26 февраля 2020

Если вы используете Set Printing Coercions., сообщение об ошибке будет гораздо более информативным о проблеме:

The term "xfree" has type "disj_vars (var_to_varset x) (bound_variables g)"
while it is expected to have type
 "disj_vars (bound_variables (coerce_judgement_to_ty_ctx (judge x t)))
    (bound_variables g)"

Проблема в том, что приведение x в VarSet.t равно Var.singleton x, а принуждение в judge уменьшается до VarSet.union (VarSet.singleton x) VarSet.empty. Хотя эти два предложения пропозиционально равны, они не равны в суждении, так что в отношении Coq термин, который он придумал, имеет неверный тип.

...