I'm trying to formalize a simple type system in Coq as an exercise.
I have a type Item
and a type {x : Item | IsNormal Item}
. If Sort
is a constructor of Item
and Sort
satisfies IsNormal
, what's the most natural way to produce an instance of {x : Item | IsNormal Item}
where the Item
in question is Sort
?
I have an inductive type called Item
which might be a read of a free variable (in this case a free variable is an $\mathbb{N}$).
I want to introduce a distinction between terms that are headed by a variable read and terms that are definitely not headed by a variable.
I'm trying to use sig types
for this (see this answer and this link).
The thing I am having problems with is this definition. (I also tried a shorter version with match x with | Read x' => env x' | _ => x end
as the body)
Definition in_env (env : nat -> NormalItem) (x : Item) : NormalItem :=
match x with
| Read x' => env x'
| Sort => Sort
| N => N
| T => T
| Nat n => Nat n
end.
NormalItem
is defined as { x : Item | IsNormal x }
, where IsNormal
picks out the members of Item
that are not headed by Read
.
This definition doesn't type check (error shown below).
Error:
In environment
env : nat -> NormalItem
x : Item
The term "Sort" has type "Item" while it is expected to have type
"NormalItem".
I think this is because Sort
needs to instead be a pair consisting of an Item
and a proof that the item in question satisfies isNormal
. I cannot figure out, however, how to write such a thing.
Appendix A
Require Import Arith.
Require Import List.
Require Import Specif.
Require Import Notations.
Open Scope nat_scope.
Inductive Item : Type :=
| Sort : Item
| N : Item
| T : Item
| Nat : nat -> Item
| Read : nat -> Item
.
Definition IsNormal (a : Item) : Prop :=
match a with
| Read _ => False
| _ => True
end.
Definition NormalItem : Type := { x : Item | IsNormal x }.
```