Say I have the following type typ
representing bool or nat:
Inductive typ : Type := TB | TN.
I also have a function to extract an actual function type from a list of typ
s and a result type:
Fixpoint get_types (s: seq typ) (result_type: Type) : Type :=
match s with
| nil => result_type
| x :: xs => match x with
| TN => nat -> get_types xs result_type
| TB => bool -> get_types xs result_type
end
end.
Example get_types_works : get_types (TB :: TN :: nil) nat = bool -> nat -> nat.
Proof. by []. Qed.
Now, I have another function that takes as input a list s
of typ
s and a function of type get_types s
:
Fixpoint app (s: seq typ) (constructor: get_types s nat) : nat :=
match s with
| nil => 2 (* Not properly handling empty list case for now *)
| TB :: nil => constructor true
| TN :: nil => constructor 2
| TB :: xs => app xs (constructor true)
| TN :: xs => app xs (constructor 2)
end.
Defining the above function fails at the line | TB :: nil => constructor true
with:
Illegal application (Non-functional construction):
The expression "constructor" of type "get_types s nat" cannot be applied to the term
"true" : "bool"
Given we know here that the type of get_types s nat
should be bool -> nat
, as the value of s
is TB :: nil
, I'm wondering if there's a way we can make Coq aware of this so that the above function can be defined?
If not, is this a limitation of Coq or would the same apply to other dependently typed languages?
Edit: For context, this is not the original problem I'm trying to solve; it's a condensed version to show the issue I was having with the type system. In the actual version, rather than hard-coding 2
and true
, the typ
-like datastructure also carries indices of data to parse from a memory slice, and validation functions. The aim for app
is a function that takes a list of such typ
s, a slice, and a constructor for a record containing such types, then constructs an instance of that record from the indices of the types to parse, or returns None
if any of the validations fail.
Fixpoint app (s: list typ) : forall (constructor: get_types s nat), nat := match s return get_types s nat -> nat with | nil => fun constructor => constructor | TN :: xs => fun constructor => app xs (constructor 2) | TB :: xs => fun constructor => app xs (constructor true) end.
? – Jason GrossThe term "xs" has type "seq typ" while it is expected to have type "get_types ?s nat"
. This is on Coq 8.7. – LogicChainsImplicit Arguments
set? Try replacing the calls toapp
with calls to@app
. – Jason Gross