Eval compute is incomplete when own decidability is used in Coq - coq

The Eval compute command does not always evaluate to a simple expression.
Consider the code:
Require Import Coq.Lists.List.
Require Import Coq.Arith.Peano_dec.
Import ListNotations.
Inductive I : Set := a : nat -> I | b : nat -> nat -> I.
Lemma I_eq_dec : forall x y : I, {x = y}+{x <> y}.
Proof.
repeat decide equality.
Qed.
And, if I execute the following command:
Eval compute in (if (In_dec eq_nat_dec 10 [3;4;5]) then 1 else 2).
Coq tells me that the result is 2. However, when I execute the following expression:
Eval compute in (if (In_dec I_eq_dec (a 2) [(a 1);(a 2)]) then 1 else 2).
I get a long expression where the In-predicate seems to be unfolded, but no result is given.
What do I have to change to obtain the answer 1 in the last Eval compute line ?

In Coq there are two terminator commands for proof scripts: Qed and Defined. The difference between them is that the former creates opaque terms, which cannot be unfolded, even by Eval compute. The latter creates transparent terms, which can then be unfolded as usual. Thus, you just have to put Defined in the place of Qed.:
Require Import Coq.Lists.List.
Require Import Coq.Arith.Peano_dec.
Import ListNotations.
Inductive I : Set := a : nat -> I | b : nat -> nat -> I.
Lemma I_eq_dec : forall x y : I, {x = y}+{x <> y}.
Proof.
repeat decide equality.
Defined.
Eval compute in (if (In_dec I_eq_dec (a 2) [(a 1);(a 2)]) then 1 else 2).
I personally find the sumbool type {A} + {B} not very nice for expressing decidable propositions, precisely because proofs and computation are too tangled together; in particular, proofs affect how terms reduce. I find it better to follow the Ssreflect style, separate proofs and computation and relate them via a special predicate:
Inductive reflect (P : Prop) : bool -> Set :=
| ReflectT of P : reflect P true
| ReflectF of ~ P : reflect P false.
this gives a convenient way for saying that a boolean computation returns true iff some property is true. Ssreflect provides support for conveniently switching between the computational boolean view and the logical view.

If you want to evaluate your proofs, you need to make them transparent. You do that by finishing them with the Defined command. The Qed command makes them opaque, meaning it discards their computational content.

Related

Weird goal `Some 0 = true` generated in proof

Consider this toy Coq problem (CollaCoq):
Require Import ssreflect ssrfun ssrbool.
Require Import Unicode.Utf8.
Definition optfun (n: nat) : option nat :=
match n with
| 0 => Some 0
| _ => None
end.
Definition boolfun (n: nat) : bool :=
match n with
| 0 => true
| _ => false
end.
Lemma lem : ∀ n, isSome (optfun n) = boolfun n.
Proof.
intro. unfold optfun, boolfun. destruct n.
My goal here was to have boolfun be true whenever optfun returns a Some, and to prove that in the lemma.
However, after the proof steps given, the current subgoal is Some 0 = true.
I thought a proposition like that should not even type check because I'd expect Some 0 to be of type option nat and true to be of type bool. Why does this happen? Is there something wrong with my optfun, boolfun or lem?
If we run Set Printing Coercions., we can see all the implicit coercions in our expression (by default, Coq hides them). In our case, the goal turns into isSome (Some 0), because SSReflect adds a coercion between option and bool. By running Set Coercion Paths option bool., we see that isSome itself is the coercion in question (see this part of the standard library).

Unable to prove that only 0 is less than 1 with mathcomp's finTypes

This question might seem very stupid, but I'm unable to prove that the only natural number
less than 1 is 0. I'm using mathcomp's finType library, and the goal that I want to prove is:
Lemma ord0_eq1 (a : ordinal 1) : a = ord0.
The problem is that if I destruct a and ord0 I obtain the following goal:
∀ (m : nat) (i : (m < 1)%N), Ordinal i = Ordinal (ltn0Sn 0)
Now I may use case and derive absurd if m is not equal to 0. But if m is equal to 0, I get:
∀ i : (0 < 1)%N, Ordinal i = Ordinal (ltn0Sn 0)
And the only way to prove this equality is to prove that forall i : 0 < 1, i = (ltn0Sn 0).
But I don't know how to prove equality between two proofs of the same Prop without using
proof irrelevance, and I don't want to add an axiom to my theory.
There must be some way to use Ssreflect's reflection capabilities to solve this goal, but I
haven't found anything: I can get to the point where I need to prove the equality between two
proofs of an equality and I could use UIP (uniqueness of identity proofs), but that's another
axiom and I don't want to use it.
I can't believe that I have to add an axiom to prove this goal: the
less-than relation can only be determined by computation. There should be
a way to prove that forall (m n : nat) (a b : m < n), a = b without UIP or proof irrelevance.
Thanks
EDIT: I am using mathcomp's ssrnat library and not Coq's Arith module. The "<" notation is bound to ssrnat's ltn, not to Arith's lt.
The predicate defining the ordinal type is a boolean equality, hence satisfies proof irrelevance. In cases like this, you can appeal to val_inj:
From mathcomp Require Import all_ssreflect.
Lemma ord0_eq1 (a : ordinal 1) : a = ord0.
Proof. by apply/val_inj; case: (val a) (valP a). 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.

Counting number of different elements in a list in Coq

I'm trying to write a function that takes a list of natural numbers and returns as output the amount of different elements in it. For example, if I have the list [1,2,2,4,1], my function DifElem should output "3". I've tried many things, the closest I've gotten is this:
Fixpoint DifElem (l : list nat) : nat :=
match l with
| [] => 0
| m::tm =>
let n := listWidth tm in
if (~ In m tm) then S n else n
end.
My logic is this: if m is not in the tail of the list then add one to the counter. If it is, do not add to the counter, so I'll only be counting once: when it's the last time it appears. I get the error:
Error: The term "~ In m tm" has type "Prop"
which is not a (co-)inductive type.
In is part of Coq's list standard library Coq.Lists.List. It is defined there as:
Fixpoint In (a:A) (l:list A) : Prop :=
match l with
| [] => False
| b :: m => b = a \/ In a m
end.
I think I don't understand well enough how to use If then statements in definitions, Coq's documentation was not helpful enough.
I also tried this definition with nodup from the same library:
Definition Width (A : list nat ) := length (nodup ( A ) ).
In this case what I get as error is:
The term "A" has type "list nat" while it is expected to have
type "forall x y : ?A0, {x = y} + {x <> y}".
And I'm quiet confused as to what's going on here. I'd appreciate your help to solve this issue.
You seem to be confusing propositions (Prop) and booleans (bool). I'll try to explain in simple terms: a proposition is something you prove (according to Martin-Lof's interpretation it is a set of proofs), and a boolean is a datatype which can hold only 2 values (true / false). Booleans can be useful in computations, when there are only two possible outcomes and no addition information is not needed. You can find more on this topic in this answer by #Ptival or a thorough section on this in the Software Foundations book by B.C. Pierce et al. (see Propositions and Booleans section).
Actually, nodup is the way to go here, but Coq wants you to provide a way of deciding on equality of the elements of the input list. If you take a look at the definition of nodup:
Hypothesis decA: forall x y : A, {x = y} + {x <> y}.
Fixpoint nodup (l : list A) : list A :=
match l with
| [] => []
| x::xs => if in_dec decA x xs then nodup xs else x::(nodup xs)
end.
you'll notice a hypothesis decA, which becomes an additional argument to the nodup function, so you need to pass eq_nat_dec (decidable equality fot nats), for example, like this: nodup eq_nat_dec l.
So, here is a possible solution:
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Import ListNotations.
Definition count_uniques (l : list nat) : nat :=
length (nodup eq_nat_dec l).
Eval compute in count_uniques [1; 2; 2; 4; 1].
(* = 3 : nat *)
Note: The nodup function works since Coq v8.5.
In addition to Anton's solution using the standard library I'd like to remark that mathcomp provides specially good support for this use case along with a quite complete theory on count and uniq. Your function becomes:
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Definition count_uniques (T : eqType) (s : seq T) := size (undup s).
In fact, I think the count_uniques name is redundant, I'd prefer to directly use size (undup s) where needed.
Using sets:
Require Import MSets.
Require List. Import ListNotations.
Module NatSet := Make Nat_as_OT.
Definition no_dup l := List.fold_left (fun s x => NatSet.add x s) l NatSet.empty.
Definition count_uniques l := NatSet.cardinal (no_dup l).
Eval compute in count_uniques [1; 2; 2; 4; 1].