Case construct for Coq development - coq

It seems that at some point there was a file SfLib.v that was used for the Software Foundations course. However, the case command proposed in this file is not getting through in my case:
Require Omega. (* needed for using the [omega] tactic *)
Require Export Bool.
Require Export List.
Require Export Arith.
Require Export Arith.EqNat. (* Contains [beq_nat], among other things *)
(** * From Basics.v *)
Require String. Open Scope string_scope.
Ltac move_to_top x :=
match reverse goal with
| H : _ |- _ => try move x after H
end.
Tactic Notation "assert_eq" ident(x) constr(v) :=
let H := fresh in
assert (x = v) as H by reflexivity;
clear H.
Tactic Notation "Case_aux" ident(x) constr(name) :=
first [
set (x := name); move_to_top x
| assert_eq x name; move_to_top x
| fail 1 "because we are working on a different case" ].
Tactic Notation "Case" constr(name) := Case_aux Case name.
Tactic Notation "SCase" constr(name) := Case_aux SCase name.
Tactic Notation "SSCase" constr(name) := Case_aux SSCase name.
Tactic Notation "SSSCase" constr(name) := Case_aux SSSCase name.
Tactic Notation "SSSSCase" constr(name) := Case_aux SSSSCase name.
Tactic Notation "SSSSSCase" constr(name) := Case_aux SSSSSCase name.
Tactic Notation "SSSSSSCase" constr(name) := Case_aux SSSSSSCase name.
Tactic Notation "SSSSSSSCase" constr(name) := Case_aux SSSSSSSCase name.
Fixpoint ble_nat (n m : nat) : bool :=
match n with
| O => true
| S n' =>
match m with
| O => false
| S m' => ble_nat n' m'
end
end.
Theorem andb_true_elim1 : forall b c,
andb b c = true -> b = true.
Proof.
intros b c H.
destruct b.
Case "b = true".
reflexivity.
Case "b = false".
rewrite <- H. reflexivity. Qed.
In the first case, I'm getting No interpretation for string "b = true".
This was previously addressed in coq error when trying to use Case. Example from Software Foundations book. However, the solution there does no longer work. Should I get rid of all the case statements?

Maybe something changed since then, but now we need to Import notations.
(* 8.9, 8.10, and newer *)
From Coq Require String.
Export String.StringSyntax. (* [Export] means to [Import] the StringSyntax module, but also make it automatically available to whoever imports this file as well. *)
Open Scope string_scope.
(* 8.8 and older (still works with 8.9, 8.10, but pollutes the namespace) *)
From Coq Require Export String.
Open Scope string_scope.
However, as evidenced by the removal of the module, the benefit of this trick is quite minor. Most people just use bullets, with comments to indicate the cases if they even care to comment.
Above, Open Scope is used, which may be fine for self-contained projects like SF, but for big and open projects, to avoid surprises with notations, I would recommend only using Local Open Scope (which then needs to appear in every file), or keeping Open Scope inside inner modules (that still need to be imported explicitly, but can be reexported together with others).

Related

Avoid duplicating code for applying tactics in both hypothesis and goal

I find my self (sort of) duplicating code because I want to the same tactics in the goal and in a hypothesis when they match. For example:
match goal with
| H : PATTERN |- _ => simpl in H; rewrite X in H; ... ; other_tactic in H
| |- PATTERN => simpl ; rewrite ; ... ; other_tactic
end.
If the tactics in the match cases becomes long, I essentially duplicate it, with some in clauses added, and this seem very unsatisfactory, in particular if I have many match clauses, so that I duplicate a lot of code.
Sometimes it is not because that I am matching, but simply that I have defined a custom tactic, but depending on the context I would like to apply it either to the goal or to a named hypothesis. For example:
Ltac my_tac H := simpl in H; rewrite X in H; ... ; other_tactic in H.
Ltac my_tac_goal := simpl ; rewrite X ; ... ; other_tactic.
Then I am again "duplicating" code.
Are there any ways of avoiding this kind of duplication?
At some point I wondered of the goal had a name, say GOAL, like hypothesis, so that simpl in GOAL was equivalent to simpl, but I suspect this is not the case. In that case I could drop the definition of my_tac_goal and then just call my_tac GOAL instead.
Any suggestions on how to avoid this kind of duplication would be appreciated.
PS I had a hard time coming up with a good title, so if somebody thinks of one that fits well, do not hesitate to change it.
The "name" of the goal in an in clause is |- *, but somehow I can't find a reference in the manual for this. E.g. the following works:
Goal 2+2=4 -> 2+2=4 -> 2+2=4.
intros H1 H2.
simpl in H1 |- *.
This applies simpl in H1 and the goal, but not in H2.
Indeed, the DRY principle is often a useful pattern, including for Coq developments!
Regarding the particular use case you describe, it seems you could benefit from the SSReflect tactical in?
Proof-of-concept:
Require Import ssreflect.
Section SomeTest.
Variables (T : Type) (a b : T).
Hypothesis L : a = b.
Ltac my_tac := simpl; rewrite L.
Lemma test (c : T) (H : let _t := tt in (* dummy let-in to exemplify [simpl] *)
(a, c) = (c, b)) :
let _t := tt in (b, c) = (c, a).
do [ my_tac ] in H.
my_tac.
exact: H.
Qed.
End SomeTest.
Obviously, the do [ … ] in H form won't be applicable for any tactic (e.g., an apply/view. tactic should be manually ported to some move/view. tactic), but nothing prevents you from extending the my_tac tactic (e.g., with some if-then-else…), so that relevant parts are adapted manually (or removed) to address both kinds of contexts.

How should a user-defined enumerated type be made `finType`?

I want to make an inductively-defined enumerated type in Coq/SSReflect like
Inductive E: Type := A | B | C.
be finType because it is apparently a finite type.
I have three solutions to do it but all are involved than I expected and never be satisfactory.
In the first solution, I implemented mixin's for eqType, choiceType, countType and finType.
Require Import all_ssreflect.
Inductive E := A | B | C.
Definition E_to_ord (e:E) : 'I_3.
by apply Ordinal with (match e with A => 0 | B => 1 | C => 2 end); case e.
Defined.
Definition E_of_ord (i:'I_3) : E.
by case i=>m ltm3; apply(match m with 0 => A | 1 => B | _ => C end).
Defined.
Lemma E_cancel: cancel E_to_ord E_of_ord. by case. Qed.
Definition E_eq s1 s2 := E_to_ord s1 == E_to_ord s2.
Definition E_eqP: Equality.axiom E_eq. by do 2 case; constructor. Defined.
Canonical E_eqType := Eval hnf in EqType E (EqMixin E_eqP).
Canonical E_choiceType := Eval hnf in ChoiceType E (CanChoiceMixin E_cancel).
Canonical E_countType := Eval hnf in CountType E (CanCountMixin E_cancel).
Canonical E_finType := Eval hnf in FinType E (CanFinMixin E_cancel).
It works well but I want a simpler solution.
The second solution is to just use an ordinal type
Require Import all_ssreflect.
Definition E: predArgType := 'I_3.
Definition A: E. by apply Ordinal with 0. Defined.
Definition B: E. by apply Ordinal with 1. Defined.
Definition C: E. by apply Ordinal with 2. Defined.
but it requires an involved case analysis in further proofs (or, some lemmas need to be
defined which I don't want to do).
As the third possible solution, adhoc_seq_sub_finType could be used.
Require Import all_ssreflect.
Inductive E := A | B | C.
Definition E_to_ord (e:E) : 'I_3.
by apply Ordinal with (match e with A => 0 | B => 1 | C => 2 end); case e.
Defined.
Definition E_eq s1 s2 := E_to_ord s1 == E_to_ord s2.
Definition E_eqP: Equality.axiom E_eq. by do 2 case; constructor. Defined.
Canonical E_eqType := Eval hnf in EqType E (EqMixin E_eqP).
Definition E_fn := adhoc_seq_sub_finType [:: A; B; C].
However, it defines a different type from the original inductive type E, which means that we always need to convert them each other in further proofs. Additionally, it requires us to implement eqType (which is also obvious and could be default without any implementation).
Since I want to define many enumerated types, it wouldn't be nice to give such involved definitions for every type. A solution I expected is that such eqType and finType are almost altomatically given at the corresponding inductive definition of enumerated types.
Is there any good idea to solve the problem?
I have written a library for generic programming in Coq that allows you to write code like this:
From mathcomp Require Import ssreflect ssrfun eqtype choice seq fintype.
From CoqUtils Require Import void generic.
Inductive E := A | B | C.
(* Convince Coq that E is an inductive type *)
Definition E_coqIndMixin :=
Eval simpl in [coqIndMixin for E_rect].
Canonical E_coqIndType :=
Eval hnf in CoqIndType _ E E_coqIndMixin.
(* Derive a bunch of generic instances *)
Definition E_eqMixin :=
Eval simpl in [indEqMixin for E].
Canonical E_eqType :=
Eval hnf in EqType E E_eqMixin.
Definition E_choiceMixin :=
Eval simpl in [indChoiceMixin for E].
Canonical E_choiceType :=
Eval hnf in ChoiceType E E_choiceMixin.
Definition E_countMixin :=
Eval simpl in [indCountMixin for E].
Canonical E_countType :=
Eval hnf in CountType E E_countMixin.
Definition E_finMixin :=
Eval simpl in [indFinMixin for E].
Canonical E_finType :=
Eval hnf in FinType E E_finMixin.
The library is still experimental and is dumped into my Coq utils repository. The code is very unstable. Under the hood, it uses the induction principles automatically generated by Coq to program the operators required by all these classes. One nice feature is that the code generated for equality is pretty close to what one would write by hand -- check what you get if you write Compute (#eq_op E_eqType)!
Edit I have extracted that file into a standalone library (https://github.com/arthuraa/deriving). This will make into OPAM once it becomes more stable.
Edit 2 The package is now available as coq-deriving on the extra-dev OPAM repository (https://github.com/coq/opam-coq-archive/tree/master/extra-dev).

Match context pattern inside a tactic/tactic notation

I find a pattern inside my goal through a tactic.
Why does this fail:
Tactic Notation "my_context_match" uconstr(g) :=
match goal with
| |- context[g] => idtac
end.
my_context_match _.
While this succeeds?
match goal with
| |- context[_] => idtac
end.
Is there any way to write a my_context_match, such that I can pass incomplete patterns (with _ on them) and see if anything inside my goal matches the patter?
Support for uconstr is very patchy. I've just reported #9321. Note that even this fails:
Goal True.
let v := uconstr:(True) in
lazymatch constr:(v) with
| v => idtac
end. (* Error: No matching clauses for match. *)
As suggested by #eponier in a comment, you can use open_constr instead of uconstr. However, this will leave unresolved evars. Here is a tactic that will work, and will not leave unresolved evars:
Tactic Notation "my_context_match" uconstr(g) :=
(* [match] does not support [uconstr], cf COQBUG(https://github.com/coq/coq/issues/9321),
so we use [open_constr] *)
let g := open_constr:(g) in
(* turning [g] into an [open_constr] creates new evars, so we must
eventually unify them with the goal *)
let G := match goal with |- ?G => G end in
(* We now search for [g] in the goal, and then replace the matching
subterm with the [open_constr] [g], so that we can unify the
result with the goal [G] to resolve the new evars we created *)
match G with
| context cG[g]
=> let G' := context cG[g] in
unify G G'
end.
Goal True /\ True.
my_context_match _.
my_context_match (_ /\ _).
Fail my_context_match (_ \/ _).
my_context_match True.
exact (conj I I).
Qed.

Canonical structures in ssreflect

I'm trying to deal with canonical structures in ssreflect. There are 2 pieces of code that I took from here.
I will bring pieces for the bool and the option types.
Section BoolFinType.
Lemma bool_enumP : Finite.axiom [:: true; false]. Proof. by case. Qed.
Definition bool_finMixin := Eval hnf in FinMixin bool_enumP.
Canonical bool_finType := Eval hnf in FinType bool bool_finMixin.
Lemma card_bool : #|{: bool}| = 2. Proof. by rewrite cardT enumT unlock. Qed.
End BoolFinType.
Section OptionFinType.
Variable T : finType.
Notation some := (#Some _) (only parsing).
Local Notation enumF T := (Finite.enum T).
Definition option_enum := None :: map some (enumF T).
Lemma option_enumP : Finite.axiom option_enum.
Proof. by case => [x|]; rewrite /= count_map (count_pred0, enumP). Qed.
Definition option_finMixin := Eval hnf in FinMixin option_enumP.
Canonical option_finType := Eval hnf in FinType (option T) option_finMixin.
Lemma card_option : #|{: option T}| = #|T|.+1.
Proof. by rewrite !cardT !enumT {1}unlock /= !size_map. Qed.
End OptionFinType.
Now, suppose I have a function f from finType to Prop.
Variable T: finType.
Variable f: finType -> Prop.
Goal f T. (* Ok *)
Goal f bool. (* Not ok *)
Goal f (option T). (* Not ok *)
In the last two cases I get the following error:
The term "bool/option T" has type "Set/Type" while it is expected to have type "finType".
What am I doing wrong?
The instance search for canonical structures is a bit counter intuitive in these cases. Suppose that you have the following things:
a structure type S, and a type T;
a field proj : S -> T of S;
an element x : T; and
an element st : S that has been declared as canonical, such that proj st is defined as x.
In your example, we would have:
S = finType
T = Type
proj = Finite.sort
x = bool
st = bool_finType.
Canonical structure search is triggered only in the following case: when the type-checking algorithm is trying to find a value to validly fill in the hole in the equation proj _ = x. Then, it will use st : S to fill in this hole. In your example, you expected the algorithm to understand that bool can be used as finType, by transforming it into bool_finType, which is not quite what is described above.
To make Coq infer what you want, you need to use a unification problem of that form. For instance,
Variable P : finType -> Prop.
Check ((fun (T : finType) (x : T) => P T) _ true).
What is going on here? Remember that Finite.sort is declared as a coercion from finType to Type, so x : T really means x : Finite.sort T. When you apply the fun expression to true : bool, Coq has to find a solution for Finite.sort _ = bool. It then finds bool_finType, because it was declared as canonical. So the element of bool is what triggers the search, but not quite bool itself.
As ejgallego pointed out, this pattern is so common that ssreflect provides the special [finType of ...] syntax. But it might still be useful to understand what is going on under the hood.

Defining a finite automata Coq

I am learning Coq and I'd like to use it to formalize Regular languages theory, specially finite automata. Let's say I have a structure for an automata as follows:
Record automata : Type := {
dfa_set_states : list state;
init_state : state;
end_state : state;
dfa_func: state -> terminal -> state;
}.
Where state is an inductive type as:
Inductive state:Type :=
S.
And the type terminal terminal is
Inductive terminal:Type :=
a | b.
I am trying to define it so later I'll be able to generalize the definition for any regular language. For now, I'd want to construct an automata which recognizes the language (a * b *), which is all words over the {a,b} alphabet. Does anyone have an idea on how to build some kind of fixpoint function that will run the word (which I see as a list of terminal) and tell me if that automata recgonizes that word or not? Any idea/help will be greatly apreciated.
Thanks in advance,
Erick.
Because you're restricting yourself to regular languages, this is quite simple: you just have to use a fold. Here is a sample:
Require Import Coq.Lists.List.
Import ListNotations.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Record dfa (S A : Type) := DFA {
initial_state : S;
is_final : S -> bool;
next : S -> A -> S
}.
Definition run_dfa S A (m : dfa S A) (l : list A) : bool :=
is_final m (fold_left (next m) l (initial_state m)).
This snippet is a little bit different from your original definition in that the state and alphabet components are now type parameters of the DFA, and in that I have replaced the end state with a predicate that answers whether we are in an accepting state or not. The run_dfa function simply iterates the transition function of the DFA starting from the initial state, and then tests whether the last state is an accepting state.
You can use this infrastructure to describe pretty much any regular language. For instance, here is an automaton for recognizing a*b*:
Inductive ab := A | B.
Inductive ab_state : Type :=
ReadA | ReadB | Fail.
Definition ab_dfa : dfa ab_state ab := {|
initial_state := ReadA;
is_final s := match s with Fail => false | _ => true end;
next s x :=
match s, x with
| ReadB, A => Fail
| ReadA, B => ReadB
| _, _ => s
end
|}.
We can prove that this automaton does what we expect. Here is a theorem that says that it accepts strings of the sought language:
Lemma ab_dfa_complete n m : run_dfa ab_dfa (repeat A n ++ repeat B m) = true.
Proof.
unfold run_dfa. rewrite fold_left_app.
assert (fold_left (next ab_dfa) (repeat A n) (initial_state ab_dfa) = ReadA) as ->.
{ now simpl; induction n as [| n IH]; simpl; trivial. }
destruct m as [|m]; simpl; trivial.
induction m as [|m IH]; simpl; trivial.
Qed.
We can also state a converse, that says that it accepts only strings of that language, and nothing else. I have left the proof out; it shouldn't be hard to figure it out.
Lemma ab_dfa_sound l :
run_dfa ab_dfa l = true ->
exists n m, l = repeat A n ++ repeat B m.
Unfortunately, there is not much we can do with this representation besides running the automaton. In particular, we cannot minimize an automaton, test whether two automata are equivalent, etc. These functions also need to take as arguments lists that enumerate all elements of the state and alphabet types, S and A.