I am creating an MSetList P with elements of type String, and I would like to obtain the Powerset of P. I am not being able to figure it out.
Code below.
Thanks for your help :-)
Require Import
Coq.MSets.MSetList
Coq.Strings.String
Coq.Structures.OrdersEx.
Module set := Make OrdersEx.String_as_OT.
Definition P := set.add "A"%string (set.add "B"%string (set.add "C"%string (set.add "D"%string set.empty))).
Compute P.
Answer was provided on the Coq Discourse Forum by Yves Bertot
The construction of set shows that you are using the Make function
with a module as argument. If you type Print Make., you see that
this is a functor taking a module of type OrderedType as argument,
and it produces a module with many fields, among which t, eq,
eq_equiv, lt, lt_strorder, lt_compat, compare,
compare_spec, and eq_dec. If you type Print OrderedType., you
see that these field are the ones required to make an OrderedType.
So Make constructs all the fields that would be required to call Make
again, thus producing the powerset.
You can just type :
Module pset := Make set.
and you will simply obtain a structure of sets, whose elements are in
set.t. The following example was tested with coq 8.15.
Require Import
Coq.MSets.MSetList
Coq.Strings.String
Coq.Structures.OrdersEx.
Module set := Make OrdersEx.String_as_OT.
Module pset := Make set.
Definition set1 := set.add "A"%string set.empty.
Definition set2 := set.add "B"%string set.empty.
Definition set3 := set.add "C"%string set1.
Definition pset1 := pset.add set1 (pset.add set2 pset.empty).
Compute pset.mem set3 pset1.
Compute pset.mem set2 pset1.
The following code gives me an error:
Require Import Reals.
Require Import List.
Import ListNotations.
Open Scope R_scope.
Definition C := (R * R)%type.
Definition RtoC (r : R) : C := (r,0).
Coercion RtoC : R >-> C.
Definition lC : list C := [0;0;0;1].
Error: The term "[0; 0; 0; 1]" has type "list R" while it is expected to have type "list C".
But I've defined RtoC as a coercion and I don't see any problems when I use
Definition myC : C := 4.
How do I get Coq to apply the coercion within the list?
Related question: If I enter Check [0;0;0;1] it returns list R, inserting an implicit IZR before every number. Why does Coq think I want Rs rather than Zs?
I'm unsure there is a fully satisfying solution to your question.
Indeed, as recalled in the Coq refman:
Given a term, possibly not typable, we are interested in the problem of determining if it can be well typed modulo insertion of appropriate coercions.
and it turns out that in your example, the term [0;0;0;1] itself is typable as a list R and it is type-checked "in one go"; thereby when the [0;0;0;1] : list C type mismatch occurs, as there's no "backtracking", a coercion can't be inserted within the list elements.
So maybe you could adapt your formalization in a different way, or just use one of these workarounds:
Rewriting your term into a β-redex:
Definition lC := (fun z o => [z;z;z;o] : list C) 0 1.
Or inserting a few more typecasts around each element:
Definition lC := [0:C; 0:C; 0:C; 1:C].
Regarding your last question
Why does Coq think I want Rs rather than Zs?
this comes from your line Open Scope R_scope., which implies numeral litterals are recognized by default as belonging to R (which deals with the classical axiomatization of the real numbers formalized in the standard library Reals). More specifically, the implementation has changed in Coq 8.7, as from coq/coq#a4a76c2 (discussed in PR coq/coq#415). To sum up, a literal such as 5%R is now parsed as IZR 5, that is, IZR (Zpos (xI (xO xH))), while it used to be parsed to a much less concise term in Coq 8.6:
Rplus R1 (Rmult (Rplus R1 R1) (Rplus R1 R1)).
I wanted to write the simplest proof in Mizar mathematical theorem prover language I could think of. So I thought of the following:
there exists x \in Nat : x = 1
there isn't anything simpler that I could think of. I gave it the following attempt:
:: example of a comment
environ
vocabularies MY_MIZAR;
:: adding Natural Numbers
requirments SUBSET, NUMERALS, ARITHM;
::> *210
begin
theorem Th1:
ex x being Nat st x=1
proof
::consider x = 1
:: proof is done
x = 1;
thus Th1;
end;
::>
::> 210: Wrong item in environment declaration
but as you can see Mizar doesn't like my proof. What am I missing?
This still doesn't work:
::: example of a comment
environ
vocabularies MY_MIZAR;
::: adding Natural Numbers
requirements SUBSET, NUMERALS, ARITHM;
::> *856 *825
begin
theorem Th1:
ex x being Nat st x=1
proof
:::consider x = 1
::: proof is done
set x=1;
take x;
thus thesis;
end;
::>
::> 825: Cannot find constructors name on constructor list
::> 856: Inaccessible requirements directive
You can try the following:
1) Fix the 210: error:
x requirments (wrong spelling)
o requirements
2) There will probably be some new errors
about the contents of that line now, so when
you are starting out, it is usually good to
"borrow" an environ that already works, e.g.,
you can use the environ lines from one of the
Mizar articles on natural numbers like
NAT_1.miz:
environ
:: adding Natural Numbers
vocabularies NUMBERS, ORDINAL1, REAL_1, SUBSET_1, CARD_1, ARYTM_3, TARSKI,
RELAT_1, XXREAL_0, XCMPLX_0, ARYTM_1, XBOOLE_0, FINSET_1, FUNCT_1, NAT_1,
FUNCOP_1, PBOOLE, PARTFUN1, FUNCT_7, SETFAM_1, ZFMISC_1;
notations TARSKI, XBOOLE_0, ENUMSET1, ZFMISC_1, SUBSET_1, SETFAM_1, ORDINAL1,
FINSET_1, CARD_1, PBOOLE, NUMBERS, XCMPLX_0, XREAL_0, XXREAL_0, RELAT_1,
FUNCT_1, PARTFUN1, FUNCOP_1, FUNCT_2, BINOP_1;
constructors NUMBERS, XCMPLX_0, XXREAL_0, XREAL_0, CARD_1, WELLORD2, FUNCT_2,
PARTFUN1, FUNCOP_1, FUNCT_4, ENUMSET1, RELSET_1, PBOOLE, ORDINAL1,
SETFAM_1, ZFMISC_1, BINOP_1;
registrations SUBSET_1, ORDINAL1, NUMBERS, XXREAL_0, XREAL_0, CARD_1,
RELSET_1, FUNCT_2, PBOOLE;
requirements REAL, NUMERALS, SUBSET, BOOLE, ARITHM;
definitions SETFAM_1, TARSKI, XBOOLE_0, RELAT_1;
equalities ORDINAL1, XBOOLE_0, CARD_1;
expansions SETFAM_1, ORDINAL1, TARSKI, XBOOLE_0;
theorems AXIOMS, ORDINAL1, XCMPLX_1, XREAL_1, XXREAL_0, TARSKI, ORDINAL2,
XBOOLE_0, CARD_1, FUNCT_2, FUNCT_1, FUNCOP_1, PBOOLE, RELSET_1, RELAT_1,
PARTFUN1, SUBSET_1, NUMBERS, ENUMSET1, XBOOLE_1;
schemes SUBSET_1, ORDINAL2, FUNCT_2, PBOOLE, BINOP_1;
3) To use "1" as your example, you can use "set", "take":
proof
set x=1;
take x;
thus thesis;
end;
Hope this helps.
There are several ways to do this:
Although it is not quite your statement here is an example (It is not quite your statement because you use a "Nat" type).
environ
vocabularies NUMBERS;
constructors ARYTM_0;
notations NUMBERS;
registrations ORDINAL1;
requirements NUMERALS, SUBSET, BOOLE;
begin
1 in NAT;
ex x be object st x = 1;
ex x be object st x in NAT & x = 1;
The 3 statements are verified by mizar as valid, true, demonstrate.
If this is not demonstrated (in the mizar sense), it would indicate the *4 error or even sometimes the *1 error.
In the case of the 3 statements here, the evidence is not explicitly stated. It is contained in the environment because Mizar does not require you to indicate all the steps, some of them are automatic.
It is possible to present in this way, acceptable also to Mizar.
environ
vocabularies NUMBERS;
constructors ARYTM_0;
notations NUMBERS;
registrations ORDINAL1;
requirements NUMERALS, SUBSET, BOOLE;
begin
1 in NAT
proof
thus thesis;
end;
ex x be object st x = 1
proof
thus thesis;
end;
ex x be object st x in NAT & x = 1
proof
thus thesis;
end;
But in this situation, the full expression
proof
thus thesis;
end;
is redundant.
To return to the initial problem, and using the suggestion (user10715283 & user10715216). "can we take an environ that is smaller [...]": yes with a specific tool (clearenv.pl, provide with Mizar-System)
environ
vocabularies NAT_1;
constructors NUMBERS, XCMPLX_0, XREAL_0, BINOP_1;
notations ORDINAL1;
registrations ORDINAL1;
requirements NUMERALS, SUBSET;
begin
theorem Th1:
ex x being Nat st x=1
proof
set x=1;
take x;
thus thesis;
end;
If one has many hypothesis of the form a = b (I find that this happens often when we useinversion), is there some way to prevent a substitution from happening?
I often have Hypothesis that look like
H0: rec = someLargeRecord { field := val1; ...; fieldn := valn }
rel1: some_relation rec rec'
rel2: some_relation rec rec''
equal1: a = b
equal2: b = c
...
equal3: y = z
On running subst at this point, rel1, rel2 and the like blow up, become something of the form
rel1: some_relation someLargeRecord { field := val1; ...; fieldn := valn } rel'
rel2: some_relation someLargeRecord { field := val1; ...; fieldn := valn }
rel''
This is horrible to work with.
I wish to somehow control subst, preferably to ask it to not consider H0. Is this at all possible?
Thanks!
You can tell subst what variables to substitute. For instance, the call
subst a b y.
would substitute a, b and c, but not rec. This might not be convenient if you are trying to substitute several variables; in this case, you can put the equation that you want to keep back into the goal before calling subst. For example, the following snippet would substitute every variable in your context except for rec.
revert H0.
subst.
intros H0.
How can one see the exact implementation of an in-built tactic in Coq ? More specifically is there an alternative to Print Ltac <user-defined-tactics> which works for locating the exact definition of in-built Tactics in Coq ?
No, there is no alternative to Print Ltac. In part, this is because the built-in tactics are implemented in OCaml, and the parts they are made of aren't always expressible in terms of more primitive tactics in Ltac (and almost never would such a translation be exact). The only way I know to find the definitions is to go source-diving. If you search for, e.g., "destruct", you will find in plugins/ltac/g_tactic.ml4 the lines
| IDENT "destruct"; icl = induction_clause_list ->
TacAtom (Loc.tag ~loc:!#loc ## TacInductionDestruct(false,false,icl))
which says that destruct gets parsed as the atomic tactic node TacInductionDestruct. Searching for TacInductionDestruct gives an implementation in plugins/ltac/tacinterp.ml:
(* Derived basic tactics *)
| TacInductionDestruct (isrec,ev,(l,el)) ->
(* spiwack: some unknown part of destruct needs the goal to be
prenormalised. *)
Proofview.Goal.nf_enter begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = project gl in
let sigma,l =
List.fold_left_map begin fun sigma (c,(ipato,ipats),cls) ->
(* TODO: move sigma as a side-effect *)
(* spiwack: the [*p] variants are for printing *)
let cp = c in
let c = interp_destruction_arg ist gl c in
let ipato = interp_intro_pattern_naming_option ist env sigma ipato in
let ipatsp = ipats in
let sigma,ipats = interp_or_and_intro_pattern_option ist env sigma ipats in
let cls = Option.map (interp_clause ist env sigma) cls in
sigma,((c,(ipato,ipats),cls),(cp,(ipato,ipatsp),cls))
end sigma l
in
let l,lp = List.split l in
let sigma,el =
Option.fold_left_map (interp_open_constr_with_bindings ist env) sigma el in
Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS sigma)
(name_atomic ~env
(TacInductionDestruct(isrec,ev,(lp,el)))
(Tactics.induction_destruct isrec ev (l,el)))
end
You can find the implementation of Tactics.induction_destruct in tactics/tactics.ml.
Most primitive tactics start in one of two ways: either there is an entry in g_tactic.ml4 which says how to parse that tactic as an atomic tactic node, or there is a TACTIC EXTEND somewhere, e.g., for revert, we have in plugins/ltac/coretactics.ml4
TACTIC EXTEND revert
[ "revert" ne_hyp_list(hl) ] -> [ Tactics.revert hl ]
END
If the definition is as a node in the Ltac AST, then the place to look is tacinterp.ml, which describes how to interpret those tactics. Either way, you can continue chasing down OCaml definitions to see how tactics are implemented.