coq


All-quantified type variable in (value) constructor cannot be explicitly typed as wanted


I have the following GADT.
Inductive GADT : Type -> Type :=
| A : forall A, GADT A
| B : GADT bool.
And the following data type that has one constructor with an all-qualified type variable.
Inductive Wrap A :=
| wrap : GADT A -> Wrap A
| unwrap : forall X, GADT X -> (X -> Wrap A) -> Wrap A.
Then I want to define a recursive function that uses the function within unwrap.
Fail Fixpoint wrappedGADT {A} (xs: Wrap A) : option (GADT A) :=
match xs with
| wrap _ x => Some x
| unwrap _ _ fx k => match fx with
| A _ => None
| B => wrappedGADT (k true)
end
end.
With this definition I get the following error message.
The term "true" has type "bool" while it is expected to have type "T".
I was assuming that when I inspect fx and get case B, the parameter fx has type GADT bool, thus, the all-quantified type variable X is bool as well. Is this assumption wrong?
Next, I tried to explicitly type unwrap as follows.
Fail Fixpoint wrappedGADT {A} (xs: Wrap A) : option (GADT A) :=
match xs with
| wrap _ x => Some x
| #nwrap _ bool fx k => match fx with
| A _ => None
| B => wrappedGADT (k true)
end
end.
With this definition I get a very weird error message.
The term "true" has type "Datatypes.bool" while it is expected to have type "bool".
Can anybody give any pointers to the origin of this problem?
Unfortunately, raw match statements in Coq aren't always very smart about the kind of reasoning you're applying here. The "convoy pattern" (see CPDT for more information about it) is usually the answer for resolving this type of problem. The immediate application here would look something like:
Fail Fixpoint wrappedGADT {A} (xs: Wrap A) {struct xs} : option (GADT A) :=
match xs with
| wrap _ x => Some x
| unwrap _ _ fx k => match fx in (GADT T)
return ((T -> Wrap A) -> option (GADT A)) with
| A _ => fun k0 => None
| B => fun k0 => wrappedGADT (k0 true)
end k
end.
However, this runs into another issue, that Coq isn't able to verify the termination condition after passing the function through the "convoy". It seems that to work around that, it suffices to first define the function of recursive calls on values of k and then convoy that instead:
Fixpoint wrappedGADT {A} (xs: Wrap A) {struct xs} : option (GADT A) :=
match xs with
| wrap _ x => Some x
| unwrap _ _ fx k => let r := fun x => wrappedGADT (k x) in
match fx in (GADT T)
return ((T -> option (GADT A)) -> option (GADT A)) with
| A _ => fun _ => None
| B => fun r' => r' true
end r
end.
For your second code attempt, you're creating a local variable bool to hold the type called X in the unwrap constructor, which is then shadowing the Datatypes.bool definition. In general, there's no way to match only on one specific type in the Coq kernel language (although typeclasses provide a way to simulate that, somewhat).
Here is an alternative implementation, which constructs wrappedGADT's body using tactics. It has one advantage that it doesn't require manual return annotations from the user. The overall structure closely resembles your original code with the match expression.
It is crucial to use induction xs as opposed to destruct xs here, because the Wrap type is recursive.
Fixpoint wrappedGADT' {A} (xs: Wrap A) : option (GADT A).
induction xs as [x | ? fx k r].
- exact (Some x).
- destruct fx as [T | ].
+ exact None.
+ exact (r true).
Defined.
Print wrappedGADT'.
Here is a proof that the two implementations are extensionally equal.
Goal forall (A : Type) (xs : Wrap A),
wrappedGADT xs = wrappedGADT' xs.
Proof with auto.
intros A xs.
induction xs...
destruct g...
simpl; rewrite H; destruct (w true)...
Qed.
If we look at the term generated for wrappedGADT' (using Print wrappedGADT'.), we'll be able to construct one more solution using the Wrap_rect induction principle generated for the Wrap datatype (I just removed unused variable k from the match expression in wrappedGADT'):
Definition wrappedGADT'' {A} (xs: Wrap A) : option (GADT A) :=
Wrap_rect _
_
(fun t => Some t)
(fun _ fx k r =>
match fx in (GADT T)
return ((T -> option (GADT A)) -> option (GADT A)) with
| A _ => fun _ => None
| B => fun r' => r' true
end r)
xs.
This solution can then lead to a solution a-la Daniel's, if we unfold Wrap_rect, implemented as Fixpoint itself.

Related Links

Equality in COQ for enumerated types
Using “rewrite [hypothesis with implication]”
Confused by Coq imports
Behaviour of the apply tactic when the goal and the applied term match
Is there a ring or field tactic that can solve existential variables in Coq?
Proof by case analysis in Coq
How to let COQ write complete proof log?
How to compile Logic.v in Coq
is there a `eapply`-like tactic that works on `exists` goals in Coq?
rewrite works for = but not for <-> (iff) in Coq
Passing patterns to tactics
How to automatically introduce symmetries into Coq hypotheses?
How to save the current goal / subgoal as an `assert` lemma
How to introduce a new existential condition from a witness in Coq?
How to use a custom induction principle in Coq?
How to proof consistency in a COQ theory

Categories

HOME
cakephp
date
image-processing
raspberry-pi
alfresco
razor
sharepoint-designer
c#-2.0
modelica
vb.net-2010
remote-access
iolanguage
openrefine
pc
database-replication
text-rendering
nhibernate-envers
emulator
jtextfield
cx-freeze
mps
css-animations
captiveportal
format-specifiers
trading
cas
centos6.5
url-scheme
bootstrap-material-design
social-media
xacml
buck
msys2
file-rename
unboundid
nouislider
javascriptcore
column-family
webtest
hybridauth
amazon-kinesis-kpl
android-ble
dosbox
streamreader
optix
reportingservices-2005
janrain
unixodbc
modelmapper
osx-mavericks
font-size
pdfclown
word-vba-mac
spring-android
log4c
underscore.js-templating
asp.net-4.5
plottable.js
qgraphicsview
rtbkit
ios8-today-widget
cyclomatic-complexity
wireshark-dissector
content-length
method-parameters
umbraco6
id3v2
jubula
phpthumb
htmlcleaner
srs
mcts
gridfs
batterylevel
plasma
sublist
bitsharp
cisco-jtapi
regsvr32
fireworks
gnustep
vdsp
servicehost
webkit.net
spec#
mediarss
scripting-languages
msdev
grid-system

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App