doc-src/TutorialI/Types/Pairs.thy
author wenzelm
Tue, 16 Jan 2001 00:25:00 +0100
changeset 10902 0f512daadbd5
parent 10885 90695f46440b
child 11149 e258b536a137
permissions -rw-r--r--
split_conv;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     1
(*<*)theory Pairs = Main:(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     2
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     3
section{*Pairs*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     4
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     5
text{*\label{sec:products}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     6
Pairs were already introduced in \S\ref{sec:pairs}, but only with a minimal
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     7
repertoire of operations: pairing and the two projections @{term fst} and
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     8
@{term snd}. In any nontrivial application of pairs you will find that this
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     9
quickly leads to unreadable formulae involvings nests of projections. This
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    10
section is concerned with introducing some syntactic sugar to overcome this
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    11
problem: pattern matching with tuples.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    12
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    13
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    14
subsection{*Pattern Matching with Tuples*}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    15
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    16
text{*
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    17
Tuples may be used as patterns in $\lambda$-abstractions,
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    18
for example @{text"\<lambda>(x,y,z).x+y+z"} and @{text"\<lambda>((x,y),z).x+y+z"}. In fact,
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    19
tuple patterns can be used in most variable binding constructs,
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    20
and they can be nested. Here are
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    21
some typical examples:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    22
\begin{quote}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    23
@{term"let (x,y) = f z in (y,x)"}\\
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    24
@{term"case xs of [] => 0 | (x,y)#zs => x+y"}\\
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    25
@{text"\<forall>(x,y)\<in>A. x=y"}\\
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    26
@{text"{(x,y,z). x=z}"}\\
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    27
@{term"\<Union>(x,y)\<in>A. {x+y}"}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    28
\end{quote}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    29
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    30
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    31
text{*
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    32
The intuitive meanings of these expressions should be obvious.
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    33
Unfortunately, we need to know in more detail what the notation really stands
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    34
for once we have to reason about it.  Abstraction
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    35
over pairs and tuples is merely a convenient shorthand for a more complex
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    36
internal representation.  Thus the internal and external form of a term may
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    37
differ, which can affect proofs. If you want to avoid this complication,
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    38
stick to @{term fst} and @{term snd} and write @{term"%p. fst p + snd p"}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    39
instead of @{text"\<lambda>(x,y). x+y"} (which denote the same function but are quite
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    40
different terms).
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    41
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    42
Internally, @{term"%(x,y). t"} becomes @{text"split (\<lambda>x y. t)"}, where
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
    43
@{term split}\indexbold{*split (constant)}
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
    44
is the uncurrying function of type @{text"('a \<Rightarrow> 'b
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    45
\<Rightarrow> 'c) \<Rightarrow> 'a \<times> 'b \<Rightarrow> 'c"} defined as
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    46
\begin{center}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    47
@{thm split_def}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    48
\hfill(@{thm[source]split_def})
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    49
\end{center}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    50
Pattern matching in
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    51
other variable binding constructs is translated similarly. Thus we need to
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    52
understand how to reason about such constructs.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    53
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    54
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    55
subsection{*Theorem Proving*}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    56
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    57
text{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    58
The most obvious approach is the brute force expansion of @{term split}:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    59
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    60
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    61
lemma "(\<lambda>(x,y).x) p = fst p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    62
by(simp add:split_def)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    63
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    64
text{* This works well if rewriting with @{thm[source]split_def} finishes the
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    65
proof, as it does above.  But if it doesn't, you end up with exactly what
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    66
we are trying to avoid: nests of @{term fst} and @{term snd}. Thus this
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    67
approach is neither elegant nor very practical in large examples, although it
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    68
can be effective in small ones.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    69
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    70
If we step back and ponder why the above lemma presented a problem in the
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    71
first place, we quickly realize that what we would like is to replace @{term
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    72
p} with some concrete pair @{term"(a,b)"}, in which case both sides of the
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    73
equation would simplify to @{term a} because of the simplification rules
10902
0f512daadbd5 split_conv;
wenzelm
parents: 10885
diff changeset
    74
@{thm split_conv[no_vars]} and @{thm fst_conv[no_vars]}.  This is the
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    75
key problem one faces when reasoning about pattern matching with pairs: how to
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    76
convert some atomic term into a pair.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    77
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    78
In case of a subterm of the form @{term"split f p"} this is easy: the split
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    79
rule @{thm[source]split_split} replaces @{term p} by a pair:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    80
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    81
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    82
lemma "(\<lambda>(x,y).y) p = snd p"
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
    83
apply(split split_split);
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    84
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    85
txt{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    86
@{subgoals[display,indent=0]}
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    87
This subgoal is easily proved by simplification. Thus we could have combined
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    88
simplification and splitting in one command that proves the goal outright:
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    89
*}
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    90
(*<*)
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    91
by simp
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    92
lemma "(\<lambda>(x,y).y) p = snd p"(*>*)
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    93
by(simp split: split_split)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    94
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    95
text{*
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    96
Let us look at a second example:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    97
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    98
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    99
lemma "let (x,y) = p in fst p = x";
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   100
apply(simp only: Let_def)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   101
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   102
txt{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   103
@{subgoals[display,indent=0]}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   104
A paired @{text let} reduces to a paired $\lambda$-abstraction, which
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   105
can be split as above. The same is true for paired set comprehension:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   106
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   107
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   108
(*<*)by(simp split:split_split)(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   109
lemma "p \<in> {(x,y). x=y} \<longrightarrow> fst p = snd p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   110
apply simp
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   111
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   112
txt{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   113
@{subgoals[display,indent=0]}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   114
Again, simplification produces a term suitable for @{thm[source]split_split}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   115
as above. If you are worried about the funny form of the premise:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   116
@{term"split (op =)"} is the same as @{text"\<lambda>(x,y). x=y"}.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   117
The same procedure works for
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   118
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   119
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   120
(*<*)by(simp split:split_split)(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   121
lemma "p \<in> {(x,y). x=y} \<Longrightarrow> fst p = snd p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   122
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   123
txt{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   124
except that we now have to use @{thm[source]split_split_asm}, because
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   125
@{term split} occurs in the assumptions.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   126
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   127
However, splitting @{term split} is not always a solution, as no @{term split}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   128
may be present in the goal. Consider the following function:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   129
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   130
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   131
(*<*)by(simp split:split_split_asm)(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   132
consts swap :: "'a \<times> 'b \<Rightarrow> 'b \<times> 'a"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   133
primrec
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   134
  "swap (x,y) = (y,x)"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   135
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   136
text{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   137
Note that the above \isacommand{primrec} definition is admissible
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   138
because @{text"\<times>"} is a datatype. When we now try to prove
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   139
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   140
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   141
lemma "swap(swap p) = p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   142
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   143
txt{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   144
simplification will do nothing, because the defining equation for @{term swap}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   145
expects a pair. Again, we need to turn @{term p} into a pair first, but this
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   146
time there is no @{term split} in sight. In this case the only thing we can do
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   147
is to split the term by hand:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   148
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   149
apply(case_tac p)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   150
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   151
txt{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   152
@{subgoals[display,indent=0]}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   153
Again, @{text case_tac} is applicable because @{text"\<times>"} is a datatype.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   154
The subgoal is easily proved by @{text simp}.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   155
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   156
Splitting by @{text case_tac} also solves the previous examples and may thus
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   157
appear preferable to the more arcane methods introduced first. However, see
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   158
the warning about @{text case_tac} in \S\ref{sec:struct-ind-case}.
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   159
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   160
In case the term to be split is a quantified variable, there are more options.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   161
You can split \emph{all} @{text"\<And>"}-quantified variables in a goal
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   162
with the rewrite rule @{thm[source]split_paired_all}:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   163
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   164
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   165
(*<*)by simp(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   166
lemma "\<And>p q. swap(swap p) = q \<longrightarrow> p = q"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   167
apply(simp only:split_paired_all)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   168
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   169
txt{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   170
@{subgoals[display,indent=0]}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   171
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   172
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   173
apply simp
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   174
done
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   175
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   176
text{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   177
Note that we have intentionally included only @{thm[source]split_paired_all}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   178
in the first simplification step. This time the reason was not merely
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   179
pedagogical:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   180
@{thm[source]split_paired_all} may interfere with certain congruence
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   181
rules of the simplifier, i.e.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   182
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   183
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   184
(*<*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   185
lemma "\<And>p q. swap(swap p) = q \<longrightarrow> p = q"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   186
(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   187
apply(simp add:split_paired_all)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   188
(*<*)done(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   189
text{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   190
may fail (here it does not) where the above two stages succeed.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   191
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   192
Finally, all @{text"\<forall>"} and @{text"\<exists>"}-quantified variables are split
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   193
automatically by the simplifier:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   194
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   195
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   196
lemma "\<forall>p. \<exists>q. swap p = swap q"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   197
apply simp;
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   198
done
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   199
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   200
text{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   201
In case you would like to turn off this automatic splitting, just disable the
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   202
responsible simplification rules:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   203
\begin{center}
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
   204
@{thm split_paired_All[no_vars]}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   205
\hfill
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   206
(@{thm[source]split_paired_All})\\
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
   207
@{thm split_paired_Ex[no_vars]}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   208
\hfill
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   209
(@{thm[source]split_paired_Ex})
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   210
\end{center}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   211
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   212
(*<*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   213
end
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   214
(*>*)