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

Why is Coq prepending “Top.” to my terms?
Proving a theorem about ordered lists
Strong Induction on Lists
What does the simpl tactic do in COQ
Induction on predicates with product type arguments
Construct Sets in Coq
Is this relationship between forall and exists provable in Coq/intuitionistic logic?
Proof automation in Coq how to factorize a proof
How to use matched case and variable equivalence in coq
Proof with false hypothesis in Isabelle/HOL Isar
Is there a convention for the order of applying ssreflect tactic/taticals?
How to systematically normalize inequalities to < (lt) and <= (le) in Coq?
Inductive subset of an inductive set in Coq
How to find the source file for an identifier in Coq
Coq “Unknown interpretation for notation” error
How to switch the current goal in Coq?

Categories

HOME
xamarin
multithreading
bluetooth
tesseract
react-router
programming-languages
filtering
react-redux
analysis
youtube-api-v3
ip
cross-validation
facebook-php-sdk
etl
remote-access
ibm-odm
hapi
dosgi
opentracing
jprofiler
grails3
nas
ehcache
accessor
dcevm
format-specifiers
restful-authentication
semantic-analysis
tooltipster
entitlements
ecto
karaf
google-sites-2016
scorm2004
winrt-xaml-toolkit
caret
sequential
catalog
c11
sqlite2
squib
broadcastreceiver
preconditions
botbuilder
heightmap
google-datalayer
xml-documentation
scrollable
chain-builder
apache-fop
qsslsocket
errordocument
winscp-net
tropo
lowpass-filter
drupal-6
lift-json
windows-mobile-6.5
hittest
bind9
yt-project
google-feed-api
android-textview
fody
nsfilemanager
mathematica-frontend
player
qpid
packagist
suffix-tree
r-tree
lib.web.mvc
teamcity-8.0
icu4j
android-listview
ibaction
cisco-ios
system32
composite
bridge.net
jsapi
csquery
tt-news
xojo
mesa
yorick
transcoding
concurrent-collections
gridfs
sitemesh
blending
lcs
sublist
bitsharp
nsnetservice
coderush
gdata-api
propertyeditor
datawindow
appconkit
regsvr32
whoosh
heartbeat
krl
gamma
temporal-database
premature-optimization
geneva-server
signal-handling

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App