An outline of the kind of proof you are asking about follows. I included the base case. The inductive case is left for you. Make sure you use the assumption mentioned in the outline somewhere in the inductive case to complete it. I am using =
for "equality" and =>
for evaluation. I don't know what relations are available in your context, what you are allowed to assume about evaluation and equality, or whether you are allowed to use lemmas about @
or have an abstract definition available. So, you will likely have to modify this.
Proof by induction on the structure of xs
.
Case: xs = []
:
foo (foo xs ys) zs
= foo (foo [] ys) zs (* structure of xs *)
=> foo (match ([], ys) with ([], ys) -> ys | (* ... *)
(* def. of foo, substitution *)
=> foo (ys) zs (* eval. of match *)
= foo ys zs (* drop parentheses *)
= foo ys ([] @ zs) (* abstract def. of @ *)
= foo ys (xs @ zs) (* structure of xs *)
Case: xs = x::xs'
:
Here, suppose that, for all ys
, zs
, foo (foo xs' ys) zs = foo ys (xs' @ zs)
. (This is the so-called inductive hypothesis.)
foo (foo xs ys) zs
= foo (foo (x::xs') ys) zs (* structure of xs *)
= foo (match (x::xs', ys) with (* ... *) | (x::xs', ys) -> (* ... *)
(* def. of foo, substitution *)
=> foo (foo xs' (x::ys)) zs (* eval. of match *)
(* for you *)
= foo ys ((x::xs') @ zs) (* by some argument from you *)
= foo ys (xs @ zs) (* structure of xs *)
As you can see, the proof starts by picking a value to do structural induction on (you already picked xs
in your question). Then, the proof splits into cases according to all the possible ways xs
might be constructed. Since xs
is presumably a list (this is why type information is important), there are only two kinds of things it could be: it might be []
, or it might be x::xs'
for some value x
and list xs'
. This results in the base case and the inductive case, respectively. In both cases, we have to prove the same original property, but we know extra information about what xs
looks like (i.e., the "structure" of xs
).
For each case, you use the structure to figure out the statement you want to get to (approximately correct in your original question). Then, you try to simply go from the expression on the left side of the statement to the expression on the right side, using the rules of evaluation, identity, and any lemmas you have available. In the inductive case, you have an additional fact you can use about xs'
(the "inductive hypothesis"). This "direct" approach isn't going to work in all (perhaps most) cases at the level of research, but it works fine for this exercise.
The actual statements proved in the cases are
- If
xs = []
, foo (foo xs ys) zs = foo ys (xs @ zs)
; and
- If
xs = x::xs'
and foo (foo xs' ys) zs = foo ys (xs' @ zs)
, then foo (foo xs ys) zs = foo ys (xs @ zs)
.
ys
and zs
are implicitly universally quantified.