I want to prove the lemma below. I am trying to to use tactic 'destruct', but I
can't prove it. Please any body guide me how can I prove such lemmas. I can prove it for EmptyString, but not for variables s1 and s2. Thanks
Inductive nat : Set :=
| O : nat
| S : nat -> nat.
Inductive string : Set :=
| EmptyString : string
| String : ascii -> string -> string.
Fixpoint CompStrings (sa : string) (sb : string) {struct sb}: bool :=
match sa with
| EmptyString => match sb with
| EmptyString => true
| String b sb'=> false
end
| String a sa' => match sb with
| EmptyString => false
| String b sb'=> CompStrings sa' sb'
end
end.
Lemma Eq_lenght : forall (s1 s2 : string),
(CompStrings s1 s2) = true -> (Eq_nat (length s1) (length s2)) = true.
First off, let me argue about style. You could have written your function CompStrings as this:
Fixpoint CompStrings' (sa : string) (sb : string) {struct sb}: bool :=
match sa, sb with
| EmptyString, EmptyString => true
| EmptyString, _
| _, EmptyString => false
| String a sa', String b sb'=> CompStrings sa' sb'
end.
I find it easier to read. Here is a proof it's the same as yours, in case you're suspicious:
Theorem CompStrings'ok: forall sa sb, CompStrings sa sb = CompStrings' sa sb.
Proof.
intros. destruct sa, sb; simpl; reflexivity.
Qed.
Now, this will be a two-fold answer. First I'm just going to hint you at the direction for the proof. Then, I'll give you a full proof that I encourage you not to read before you've tried it yourself.
First off, I assumed this definition of length since you did not provide it:
Fixpoint length (s: string): nat :=
match s with
| EmptyString => O
| String _ rest => S (length rest)
end.
And since I did not have Eq_nat either, I proceeded to prove that the lengths are propositionally equal. It should be fairly trivial to adapt to Eq_nat.
Lemma Eq_length' : forall (s1 s2 : string),
CompStrings s1 s2 = true ->
length s1 = length s2.
Proof.
induction s1.
(* TODO *)
Admitted.
So here is the start! You want to prove a property about the inductive data type string. The thing is, you will want to proceed by case analysis, but if you just do it with destructs, it'll never end. This is why we proceed by induction. That is, you will need to prove that if s1 is the EmptyString, then the property holds, and that if the property holds for a substring, then it holds for the string with one character added. The two cases are fairly simple, in each case you can proceed by case analysis on s2 (that is, using destruct).
Note that I did not do intros s1 s2 C. before doing induction s1.. This is fairly important for one reason: if you do it (try!), your induction hypothesis will be too constrained as it will talk about one particular s2, rather than being quantified by it. This can be tricky when you start doing proofs by induction. So, be sure to try to continue this proof:
Lemma Eq_length'_will_fail : forall (s1 s2 : string),
CompStrings s1 s2 = true ->
length s1 = length s2.
Proof.
intros s1 s2 C. induction s1.
(* TODO *)
Admitted.
eventually, you'll find that your induction hypothesis can't be applied to your goal, because it's speaking about a particular s2.
I hope you've tried these two exercises.
Now if you're stuck, here is one way to prove the first goal.
Don't cheat! :)
Lemma Eq_length' : forall (s1 s2 : string),
CompStrings s1 s2 = true ->
length s1 = length s2.
Proof.
induction s1.
intros s2 C. destruct s2. reflexivity. inversion C.
intros s2 C. destruct s2. inversion C. simpl in *. f_equal.
exact (IHs1 _ C).
Qed.
To put that in intelligible terms:
let's prove the property forall s2, CompStrings s1 s2 = true -> length s1 = s2 by induction on s1:
in the case where s1 is the EmptyString, let's look at the shape of s2:
s2 is the EmptyString, then both lengths are equal to 0, so reflexivity.;
s2 is a String _ _, so there is a contradiction in the hypothesis, shown by inversion C.;
in the case where s1 is a String char1 rest1, let's look at the shape of s2, supposing the property true for rest:
s2 is the EmptyString, so there is a contradiction in the hypothesis, show by inversion C.;
s2 is a String char2 rest2, then length s1 = S (length rest1) and length s2 = S (length rest2), therefore we need to prove S (length rest1) = S (length rest2). Also, the hypothesis C simplifies into C: CompStrings rest1 rest2 = true. It is the perfect occasion to use the induction hypothesis to prove that length rest1 = length rest2, and then use that result somehow to prove the goal.
Note that for that last step, there are many ways to proceed to prove S (length rest1) = S (length rest2). One of which is using f_equal. which asks you to prove a pairwise equality between the parameters of the constructor. You could also use a rewrite (IHs1 _ C). then use reflexivity on that goal.
Hopefully this will help you not only solve this particular goal, but get a first understanding at proofs by induction!
To close on this, here are two interesting links.
This presents the basics of induction (see paragraph "Induction on lists").
This explains, better than me, why and how to generalize your induction hypotheses. You'll learn how to solve the goal where I did intros s1 s2 C. by putting back the s2 in the goal before starting the induction, using the tactic generalize (dependent).
In general, I'd recommend reading the whole book. It's slow-paced and very didactic.
Related
I am a beginner of sml and I'm taking programming language courses at Coursera. There's a datatype and function that I don't know how to evaluate:
datatype exp = constant of int
| Negate of exp
|Add of exp * exp
|Multiply of exp * exp
fun true_of_all_constants(f,e) =
case e of
constant i => f i
| Negate e1 => true_of_all_constants(f,e1)
| Add(e1,e2) => true_of_all_constants(f,e1)
andalso true_of_all_constants(f,e2)
| Multiply(e1,e2) => true_of_all_constants(f,e1)
andalso true_of_all_constants(f,e2)
Trying to evaluate them, I always get errors:
true_of_all_constants [3,4,5];
true_of_all_constants 4;
true_of_all_constants (is_even 4, 5);
where is_even is a little helper function:
fun is_even v =
(v mod 2 = 0)
To test true_of_all_constants, what should e be replaced with? Also, could you explain what does datatype do here? I don't understand why we need "Negate" or "Add" here; why we have "exp*exp," rather than "exp+exp," for "Add?"
Fixing whitespace, the data type definition and the definition of true_of_all_constants (p, e) become:
datatype exp =
Constant of int
| Negate of exp
| Add of exp * exp
| Multiply of exp * exp
fun true_of_all_constants (p, e) =
let fun aux (Constant i) = p i
| aux (Negate e1) = aux e1
| aux (Add (e1, e2)) = aux e1 andalso aux e2
| aux (Multiply (e1, e2)) = aux e1 andalso aux e2
in aux e end
Here constant has been renamed to Constant: Both will work, but naming constructors with an uppercase letter differentiates it visually from other identifiers. And I've used an inner function, aux, to shorten the recursive expressions a bit. Instead of f I called it p for predicate, but that's a taste thing.
Trying to evaluate them, I always get errors
Here are some examples of expressions and evaluating them:
- val two_plus_two = Add (Constant 2, Constant 2);
- true_of_all_constants (fn i => i = 2, two_plus_two);
> val it = true : bool
- val two_times_neg_two = Multiply (Constant 2, Constant ~2);
- true_of_all_constants (fn i => i > 0, two_times_neg_two);
> val it = false : bool
- val two_four_six = Add (Constant 2, Add (Constant 4, Constant 6));
- fun is_even x = x mod 2 = 0;
- true_of_all_constants (is_even, two_four_six);
> val it = true : bool
could you explain what does datatype do here?
I think you should refer to a book or tutorial here.
For example, ML for the Working Programmer, ch. 4 (free PDF) deals with datatype definitions.
I don't understand why we need "Negate" or "Add" here
I don't know, either. The problem you're given in the course is entirely hypothetical.
Is it possible to define a single notation for multiple constructors in Coq? If the constructors differ by their argument types, they might be inferrable from them. A minimal (non-)working example:
Inductive A : Set := a | b | c: C -> A | d: D -> A
with C: Set := c1 | c2
with D: Set := d1 | d2.
Notation "' x" := (_ x) (at level 19).
Check 'c1. (*?6 c1 : ?8*)
In this case, constructor inference doesn't work. Maybe there's another way to specify a constructor as a variable?
You can create a typeclass with the constructors as instances and let the instance resolution mechanism infer the constructor to call for you:
Class A_const (X:Type) : Type :=
a_const : X -> A.
Instance A_const_c : A_const C := c.
Instance A_const_d : A_const D := d.
Check a_const c1.
Check a_const d2.
By the way, with Coq 8.5, if you really want a notation ' x to result in the exact constructor applied to x, rather than e.g. #a_const C A_const_c c1, then you can use ltac-terms to accomplish that:
Notation "' x" := ltac:(match constr:(a_const x) with
| #a_const _ ?f _ =>
let unfolded := (eval unfold f in f) in
exact (unfolded x)
end) (at level 0).
Check 'c1. (* c c1 : A *)
Check 'd2. (* d d2 : A *)
In fact, the idea of using an ltac-term leads to an entirely different solution from the other one I posted:
Notation "' x" := ltac:(let T := (type of x) in
let T' := (eval hnf in T) in
match T' with
| C => exact (c x)
| D => exact (d x)
end) (at level 0).
Check 'c1. (* c c1 : A *)
Check 'd2. (* d d2 : A *)
(Here the eval hnf part lets it work even if the type of the argument isn't syntactically equal to C or D, but it does reduce to one of them.)
Apparently, it's easy:
Notation "' x" := ((_:_->A) x) (at level 19).
Check 'c1. (*' c1 : A*)
I'm currently working on a lexer written in Haskell, and am almost finished, but am running into a problem for a special case token. Currently, my lexer takes an input string and breaks down the statement into tokens for numbers, variable names, and specific tokens such as "if", "else", and "then".
It works great for all of my tokens, except for one that is "000...".
I was taught to use the span function, so I have my lexer use the isDigit and isAlphaNum boolean functions to parse the input. However, because "000..." starts with a zero, it automatically returns as a number. Additionally, the period is a token in the grammar as well, so the result of inputting "000..." in my lexer currently results in "0" "." "." ".".
I'm not proficient in the language of Haskell, but is it possible to match a string using isPrint, and use cases to handle instances of strings and integers? I'm at a loss for words right now, and it seems everything I have tried broke my program. My current pattern matching part looks like this:
lexer (c:cs)
| isSpace c = lexer cs
| isDigit c = lexDigit (c:cs)
| isAlphaNum c = lexString (c:cs)
| True = InvalidToken c : lexer cs
lexString
| s1 == "if" = IfToken : lexer s2
| s1 == "else" = ElseToken : lexer s2
| s1 == "then" = ThenToken : lexer s2
| s1 == "000..." = Zero : lexer s2
| True = StringToken s1 : lexer s2
where (s1,s2) = (span isAlphaNum cs)
Any help is appreicated!
First note that the idiomatic way to approach such a task in Haskell is to use a parser combinator library, such as parsec. (It may make sense to go the traditional parser/lexer route for some applications, but this isn't really something you should code by hand – use a lexer generator, i.e. alex.)
Now, if you determined to do this by hand, and without more expressive parser combinators... you'll need to handle that special case in lexDigit, rather than lexString:
lexDigit :: String -> [Token] -- Always use type signatures!
lexDigit cs
| ("000...",s2) <- splitAt 6 cs = Zero : lexer s2
lexDigit cs = ... -- your original definition of `lexDigit`
lexString :: String -> [Token]
lexString cs = case s1 of
"if" -> IfToken : lexer s2
"else" -> ElseToken : lexer s2
"then" -> ThenToken : lexer s2
-- no clause for "000...", since it can't happen here anyway
_ -> StringToken s1 : lexer s2
where (s1,s2) = (span isAlphaNum cs)
lexer :: String -> [Token]
lexer cs#(c:cs')
| isSpace c = lexer cs'
| isDigit c = lexDigit cs
| isAlphaNum c = lexString cs
| otherwise = InvalidToken c : lexer cs'
According to this course, all constructors (for inductive types) are injective and disjoint:
...Similar principles apply to all inductively defined types: all
constructors are injective, and the values built from distinct
constructors are never equal. For lists, the cons constructor is
injective and nil is different from every non-empty list. For
booleans, true and false are unequal.
(And the inversion tactic based on this assumption)
I am just wondering how do we know this assumption holds?
How do we know that, e.g., we cannot define natural numbers based on
1) a Successor and maybe a "Double" constructor like this:
Inductive num: Type :=
| O : num
| S : num -> num
| D : num -> num.
and
2) some plus function so that one number 2 can be reached via two different sequences/routes of constructors, S (S O) and D (S O)?
What's the mechanism in Coq that ensures the above will never happen?
P.S.
I am not suggesting the above num example is possible. I am just wondering what makes it impossible.
Thanks
When you define an inductive data type in Coq, you are essentially
defining a tree type. Each constructor gives a kind of node that is
allowed to occur in your tree, and its arguments determine the
children and elements that that node can have. Finally, functions
defined on inductive types (with the match clause) can check the
constructors that were used to produce a value of that type in
arbitrary ways. This makes Coq constructors very different from
constructors you see in an OO language, for instance. An object
constructor is implemented as a regular function that initializes a
value of a given type; Coq constructors, on the other hand, are
enumerating the possible values that the representation of our type
allows. To understand this difference better, we can compare the
different functions we can define on an object in a traditional OO
language, and on an element of an inductive type in Coq. Let's use
your num type as an example. Here's an object-oriented definition:
class Num {
int val;
private Num(int v) {
this.val = v;
}
/* These are the three "constructors", even though they
wouldn't correspond to what is called a "constructor" in
Java, for instance */
public static zero() {
return new Num(0);
}
public static succ(Num n) {
return new Num(n.val + 1);
}
public static doub(Num n) {
return new Num(2 * n.val);
}
}
And here's a definition in Coq:
Inductive num : Type :=
| zero : num
| succ : num -> num
| doub : num -> num.
In the OO example, when we write a function that takes a Num
argument, there's no way of knowing which "constructor" was used to
produce that value, because this information is not stored in the
val field. In particular Num.doub(Num.succ(Num.zero())) and
Num.succ(Num.succ(Num.zero())) would be equal values.
In the Coq example, on the other hand, things change, because we can
determine which constructor was used to form a num value, thanks to
the match statement. For instance, using Coq strings, we could write
a function like this:
Require Import Coq.Strings.String.
Open Scope string_scope.
Definition cons_name (n : num) : string :=
match n with
| zero => "zero"
| succ _ => "succ"
| doub _ => "doub"
end.
In particular, even though your intended meaning for the constructors
implies that succ (succ zero) and doub (succ zero) should be
"morally" equal, we can distinguish them by applying the cons_name
function to them:
Compute cons_name (doub (succ zero)). (* ==> "doub" *)
Compute cons_name (succ (succ zero)). (* ==> "succ" *)
As a matter of fact, we can use match to distinguish between succ
and doub in arbitrary ways:
match n with
| zero => false
| succ _ => false
| doub _ => true
end
Now, a = b in Coq means that there is no possible way we can
distinguish between a and b. The above examples show why doub
(succ zero) and succ (succ zero) cannot be equal, because we can
write functions that don't respect the meaning that we had in mind
when we wrote that type.
This explains why constructors are disjoint. That they are injective
is actually also a consequence of pattern-matching. For instance,
suppose that we wanted to prove the following statement:
forall n m, succ n = succ m -> n = m
We can begin the proof with
intros n m H.
Leading us to
n, m : num
H : succ n = succ m
===============================
n = m
Notice that this goal is by simplification equivalent to
n, m : num
H : succ n = succ m
===============================
match succ n with
| succ n' => n' = m
| _ => True
end
If we do rewrite H, we obtain
n, m : num
H : succ n = succ m
===============================
match succ m with
| succ n' => n' = m
| _ => True
end
which simplifies to
n, m : num
H : succ n = succ m
===============================
m = m
At this point, we can conclude with reflexivity. This technique is
quite general, and is actually at the core of what inversion does.
There is none: the constructors O, S and D are indeed disjoint and injective but the semantics for nums you have in your head is not, as a function, injective.
That is why num would usually be considered to be a bad representation of the natural numbers: working up-to equivalence is quite annoying.
In OCaml, I have a list of strings that contains names of towns (Something like "1-New York; 2-London; 3-Paris"). I need to ask the user to type a number (if they want London they have to type 2).
I want to raise an exception message saying that the town is not valid, if the person types for example "4", in the example.
I tried this, but it doesn't work :
let chosenTown = match int_of_string (input_line stdin) with
| x > (length listOfTowns) -> raise (Err "Not a valid town")
What's the good way to code "if the chosen number is bigger than the length of the list then raise the error" ??
Pattern can't contain arbitrary expressions. It can be a constant, a constructor name, record field inside curly braces, list, array, etc.
But patterns can be guarded, e.g.
match int_of_string (input_line stding) with
| x when x >= length listOfTowns ->
invalid_arg "the number is too large"
| x -> List.nth listOfTowns x
To complete the answer, patter matching relies on unification and does not expect assertion (it is not the equivalent of a switch in C or so).
The idea is that you provide different "shapes" (patterns) that your term (the thing you match on) could have.
For a list for instance:
match l with
| e :: e' :: r -> (*...*)
| e :: r -> (*...*)
| [] -> (*...*)
It also had a binding effect, if you pass on, say, [1] (a very small list indeed), it won't match e :: e' :: r, but will match e :: r and then e = 1 and r = [].
As ivg said, you can add conditions, as booleans this time, thanks to the keyword when.
However, when manipulating lists like this, I would go for a recursive function:
let rec find_town n l =
match l with
| t :: _ when n = 1 -> t
| _ :: r -> find_town (n-1) r
| [] -> raise (Err "Not a valid town")
This is basically writing again List.nth but changing the exception that it raises.