doc-src/TutorialI/Types/Pairs.thy
author wenzelm
Sat, 14 Jun 2008 23:19:51 +0200
changeset 27208 5fe899199f85
parent 27170 65bb0ddb0b9f
permissions -rw-r--r--
proper context for tactics derived from res_inst_tac;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27170
65bb0ddb0b9f Removed hide swap
nipkow
parents: 27169
diff changeset
     1
(*<*)theory Pairs imports Main begin(*>*)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     2
11428
332347b9b942 tidying the index
paulson
parents: 11277
diff changeset
     3
section{*Pairs and Tuples*}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     4
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     5
text{*\label{sec:products}
11428
332347b9b942 tidying the index
paulson
parents: 11277
diff changeset
     6
Ordered pairs were already introduced in \S\ref{sec:pairs}, but only with a minimal
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
     7
repertoire of operations: pairing and the two projections @{term fst} and
11149
e258b536a137 *** empty log message ***
nipkow
parents: 10902
diff changeset
     8
@{term snd}. In any non-trivial application of pairs you will find that this
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
     9
quickly leads to unreadable nests of projections. This
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    10
section introduces syntactic sugar to overcome this
10560
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)"}\\
12699
deae80045527 *** empty log message ***
nipkow
parents: 12631
diff changeset
    24
@{term"case xs of [] => (0::nat) | (x,y)#zs => x+y"}\\
10560
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}
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    29
The intuitive meanings of these expressions should be obvious.
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    30
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
    31
for once we have to reason about it.  Abstraction
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    32
over pairs and tuples is merely a convenient shorthand for a more complex
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    33
internal representation.  Thus the internal and external form of a term may
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    34
differ, which can affect proofs. If you want to avoid this complication,
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    35
stick to @{term fst} and @{term snd} and write @{term"%p. fst p + snd p"}
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    36
instead of @{text"\<lambda>(x,y). x+y"}.  These terms are distinct even though they
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    37
denote the same function.
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    38
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    39
Internally, @{term"%(x,y). t"} becomes @{text"split (\<lambda>x y. t)"}, where
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    40
\cdx{split} is the uncurrying function of type @{text"('a \<Rightarrow> 'b
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    41
\<Rightarrow> 'c) \<Rightarrow> 'a \<times> 'b \<Rightarrow> 'c"} defined as
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    42
\begin{center}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    43
@{thm split_def}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    44
\hfill(@{thm[source]split_def})
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    45
\end{center}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    46
Pattern matching in
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    47
other variable binding constructs is translated similarly. Thus we need to
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    48
understand how to reason about such constructs.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    49
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    50
10885
90695f46440b lcp's pass over the book, chapters 1-8
paulson
parents: 10824
diff changeset
    51
subsection{*Theorem Proving*}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    52
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    53
text{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    54
The most obvious approach is the brute force expansion of @{term split}:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    55
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    56
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    57
lemma "(\<lambda>(x,y).x) p = fst p"
12815
wenzelm
parents: 12699
diff changeset
    58
by(simp add: split_def)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    59
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
    60
text{* \noindent
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
    61
This works well if rewriting with @{thm[source]split_def} finishes the
11149
e258b536a137 *** empty log message ***
nipkow
parents: 10902
diff changeset
    62
proof, as it does above.  But if it does not, you end up with exactly what
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    63
we are trying to avoid: nests of @{term fst} and @{term snd}. Thus this
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    64
approach is neither elegant nor very practical in large examples, although it
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    65
can be effective in small ones.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    66
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    67
If we consider why this lemma presents a problem, 
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
    68
we realize that we need to replace variable~@{term
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    69
p} by some pair @{term"(a,b)"}.  Then both sides of the
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    70
equation would simplify to @{term a} by the simplification rules
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    71
@{thm split_conv[no_vars]} and @{thm fst_conv[no_vars]}.  
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    72
To reason about tuple patterns requires some way of
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    73
converting a variable of product type into a pair.
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    74
In case of a subterm of the form @{term"split f p"} this is easy: the split
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    75
rule @{thm[source]split_split} replaces @{term p} by a pair:%
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
    76
\index{*split (method)}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    77
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    78
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    79
lemma "(\<lambda>(x,y).y) p = snd p"
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
    80
apply(split split_split);
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    81
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    82
txt{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    83
@{subgoals[display,indent=0]}
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    84
This subgoal is easily proved by simplification. Thus we could have combined
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    85
simplification and splitting in one command that proves the goal outright:
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    86
*}
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    87
(*<*)
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    88
by simp
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    89
lemma "(\<lambda>(x,y).y) p = snd p"(*>*)
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    90
by(simp split: split_split)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    91
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    92
text{*
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    93
Let us look at a second example:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    94
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    95
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    96
lemma "let (x,y) = p in fst p = x";
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
    97
apply(simp only: Let_def)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    98
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
    99
txt{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   100
@{subgoals[display,indent=0]}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   101
A paired @{text let} reduces to a paired $\lambda$-abstraction, which
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   102
can be split as above. The same is true for paired set comprehension:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   103
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   104
12815
wenzelm
parents: 12699
diff changeset
   105
(*<*)by(simp split: split_split)(*>*)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   106
lemma "p \<in> {(x,y). x=y} \<longrightarrow> fst p = snd p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   107
apply simp
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   108
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   109
txt{*
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   110
@{subgoals[display,indent=0]}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   111
Again, simplification produces a term suitable for @{thm[source]split_split}
11277
a2bff98d6e5d *** empty log message ***
nipkow
parents: 11161
diff changeset
   112
as above. If you are worried about the strange form of the premise:
27169
89d5f117add3 fixed type
nipkow
parents: 27027
diff changeset
   113
@{text"split (op =)"} is short for @{term"\<lambda>(x,y). x=y"}.
11277
a2bff98d6e5d *** empty log message ***
nipkow
parents: 11161
diff changeset
   114
The same proof procedure works for
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   115
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   116
12815
wenzelm
parents: 12699
diff changeset
   117
(*<*)by(simp split: split_split)(*>*)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   118
lemma "p \<in> {(x,y). x=y} \<Longrightarrow> fst p = snd p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   119
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   120
txt{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   121
except that we now have to use @{thm[source]split_split_asm}, because
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   122
@{term split} occurs in the assumptions.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   123
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   124
However, splitting @{term split} is not always a solution, as no @{term split}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   125
may be present in the goal. Consider the following function:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   126
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   127
12815
wenzelm
parents: 12699
diff changeset
   128
(*<*)by(simp split: split_split_asm)(*>*)
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   129
primrec swap :: "'a \<times> 'b \<Rightarrow> 'b \<times> 'a" where "swap (x,y) = (y,x)"
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   130
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   131
text{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   132
Note that the above \isacommand{primrec} definition is admissible
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   133
because @{text"\<times>"} is a datatype. When we now try to prove
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   134
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   135
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   136
lemma "swap(swap p) = p"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   137
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   138
txt{*\noindent
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   139
simplification will do nothing, because the defining equation for
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   140
@{const[source] swap} expects a pair. Again, we need to turn @{term p}
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   141
into a pair first, but this time there is no @{term split} in sight.
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   142
The only thing we can do is to split the term by hand:
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   143
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   144
apply(case_tac p)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   145
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   146
txt{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   147
@{subgoals[display,indent=0]}
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   148
Again, \methdx{case_tac} is applicable because @{text"\<times>"} is a datatype.
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   149
The subgoal is easily proved by @{text simp}.
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   150
10824
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   151
Splitting by @{text case_tac} also solves the previous examples and may thus
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   152
appear preferable to the more arcane methods introduced first. However, see
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   153
the warning about @{text case_tac} in \S\ref{sec:struct-ind-case}.
4a212e635318 *** empty log message ***
nipkow
parents: 10654
diff changeset
   154
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   155
Alternatively, you can split \emph{all} @{text"\<And>"}-quantified variables
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   156
in a goal with the rewrite rule @{thm[source]split_paired_all}:
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   157
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   158
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   159
(*<*)by simp(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   160
lemma "\<And>p q. swap(swap p) = q \<longrightarrow> p = q"
12631
wenzelm
parents: 11494
diff changeset
   161
apply(simp only: split_paired_all)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   162
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   163
txt{*\noindent
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   164
@{subgoals[display,indent=0,margin=70]}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   165
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   166
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   167
apply simp
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   168
done
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   169
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   170
text{*\noindent
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   171
Note that we have intentionally included only @{thm[source]split_paired_all}
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   172
in the first simplification step, and then we simplify again. 
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   173
This time the reason was not merely
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   174
pedagogical:
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   175
@{thm[source]split_paired_all} may interfere with other functions
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   176
of the simplifier.
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   177
The following command could fail (here it does not)
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   178
where two separate \isa{simp} applications succeed.
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   179
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   180
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   181
(*<*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   182
lemma "\<And>p q. swap(swap p) = q \<longrightarrow> p = q"
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   183
(*>*)
12815
wenzelm
parents: 12699
diff changeset
   184
apply(simp add: split_paired_all)
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   185
(*<*)done(*>*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   186
text{*\noindent
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   187
Finally, the simplifier automatically splits all @{text"\<forall>"} and
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   188
@{text"\<exists>"}-quantified variables:
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   189
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   190
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   191
lemma "\<forall>p. \<exists>q. swap p = swap q"
11494
23a118849801 revisions and indexing
paulson
parents: 11428
diff changeset
   192
by simp;
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   193
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   194
text{*\noindent
27027
63f0b638355c *** empty log message ***
nipkow
parents: 17914
diff changeset
   195
To turn off this automatic splitting, disable the
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   196
responsible simplification rules:
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   197
\begin{center}
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
   198
@{thm split_paired_All[no_vars]}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   199
\hfill
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   200
(@{thm[source]split_paired_All})\\
10654
458068404143 *** empty log message ***
nipkow
parents: 10608
diff changeset
   201
@{thm split_paired_Ex[no_vars]}
10560
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   202
\hfill
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   203
(@{thm[source]split_paired_Ex})
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   204
\end{center}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   205
*}
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   206
(*<*)
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   207
end
f4da791d4850 *** empty log message ***
nipkow
parents:
diff changeset
   208
(*>*)