doc-src/TutorialI/Types/Typedef.thy
author nipkow
Wed, 13 Dec 2000 09:39:53 +0100
changeset 10654 458068404143
parent 10420 ef006735bee8
child 10885 90695f46440b
permissions -rw-r--r--
*** empty log message ***
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10366
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     1
(*<*)theory Typedef = Main:(*>*)
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     2
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     3
section{*Introducing new types*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     4
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     5
text{*\label{sec:adv-typedef}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     6
By now we have seen a number of ways for introducing new types, for example
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     7
type synonyms, recursive datatypes and records. For most applications, this
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     8
repertoire should be quite sufficient. Very occasionally you may feel the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
     9
need for a more advanced type. If you cannot avoid that type, and you are
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    10
quite certain that it is not definable by any of the standard means,
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    11
then read on.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    12
\begin{warn}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    13
  Types in HOL must be non-empty; otherwise the quantifier rules would be
10420
ef006735bee8 *** empty log message ***
nipkow
parents: 10366
diff changeset
    14
  unsound, because $\exists x.\ x=x$ is a theorem.
10366
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    15
\end{warn}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    16
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    17
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    18
subsection{*Declaring new types*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    19
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    20
text{*\label{sec:typedecl}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    21
The most trivial way of introducing a new type is by a \bfindex{type
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    22
declaration}: *}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    23
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    24
typedecl my_new_type
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    25
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    26
text{*\noindent\indexbold{*typedecl}%
10420
ef006735bee8 *** empty log message ***
nipkow
parents: 10366
diff changeset
    27
This does not define @{typ my_new_type} at all but merely introduces its
ef006735bee8 *** empty log message ***
nipkow
parents: 10366
diff changeset
    28
name. Thus we know nothing about this type, except that it is
10366
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    29
non-empty. Such declarations without definitions are
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    30
useful only if that type can be viewed as a parameter of a theory and we do
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    31
not intend to impose any restrictions on it. A typical example is given in
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    32
\S\ref{sec:VMC}, where we define transition relations over an arbitrary type
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    33
of states without any internal structure.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    34
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    35
In principle we can always get rid of such type declarations by making those
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    36
types parameters of every other type, thus keeping the theory generic. In
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    37
practice, however, the resulting clutter can sometimes make types hard to
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    38
read.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    39
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    40
If you are looking for a quick and dirty way of introducing a new type
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    41
together with its properties: declare the type and state its properties as
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    42
axioms. Example:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    43
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    44
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    45
axioms
10420
ef006735bee8 *** empty log message ***
nipkow
parents: 10366
diff changeset
    46
just_one: "\<exists>x::my_new_type. \<forall>y. x = y"
10366
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    47
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    48
text{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    49
However, we strongly discourage this approach, except at explorative stages
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    50
of your development. It is extremely easy to write down contradictory sets of
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    51
axioms, in which case you will be able to prove everything but it will mean
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    52
nothing.  In the above case it also turns out that the axiomatic approach is
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    53
unnecessary: a one-element type called @{typ unit} is already defined in HOL.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    54
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    55
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    56
subsection{*Defining new types*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    57
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    58
text{*\label{sec:typedef}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    59
Now we come to the most general method of safely introducing a new type, the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    60
\bfindex{type definition}. All other methods, for example
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    61
\isacommand{datatype}, are based on it. The principle is extremely simple:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    62
any non-empty subset of an existing type can be turned into a new type.  Thus
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    63
a type definition is merely a notational device: you introduce a new name for
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    64
a subset of an existing type. This does not add any logical power to HOL,
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    65
because you could base all your work directly on the subset of the existing
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    66
type. However, the resulting theories could easily become undigestible
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    67
because instead of implicit types you would have explicit sets in your
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    68
formulae.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    69
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    70
Let us work a simple example, the definition of a three-element type.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    71
It is easily represented by the first three natural numbers:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    72
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    73
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    74
typedef three = "{n. n \<le> 2}"
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    75
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    76
txt{*\noindent\indexbold{*typedef}%
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    77
In order to enforce that the representing set on the right-hand side is
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    78
non-empty, this definition actually starts a proof to that effect:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    79
@{subgoals[display,indent=0]}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    80
Fortunately, this is easy enough to show: take 0 as a witness.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    81
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    82
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    83
apply(rule_tac x = 0 in exI);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    84
by simp
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    85
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    86
text{*
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    87
This type definition introduces the new type @{typ three} and asserts
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    88
that it is a \emph{copy} of the set @{term"{0,1,2}"}. This assertion
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    89
is expressed via a bijection between the \emph{type} @{typ three} and the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    90
\emph{set} @{term"{0,1,2}"}. To this end, the command declares the following
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    91
constants behind the scenes:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    92
\begin{center}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    93
\begin{tabular}{rcl}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    94
@{term three} &::& @{typ"nat set"} \\
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    95
@{term Rep_three} &::& @{typ"three \<Rightarrow> nat"}\\
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    96
@{term Abs_three} &::& @{typ"nat \<Rightarrow> three"}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    97
\end{tabular}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    98
\end{center}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
    99
Constant @{term three} is just an abbreviation (@{thm[source]three_def}):
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   100
@{thm[display]three_def}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   101
The situation is best summarized with the help of the following diagram,
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   102
where squares are types and circles are sets:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   103
\begin{center}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   104
\unitlength1mm
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   105
\thicklines
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   106
\begin{picture}(100,40)
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   107
\put(3,13){\framebox(15,15){@{typ three}}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   108
\put(55,5){\framebox(30,30){@{term three}}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   109
\put(70,32){\makebox(0,0){@{typ nat}}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   110
\put(70,20){\circle{40}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   111
\put(10,15){\vector(1,0){60}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   112
\put(25,14){\makebox(0,0)[tl]{@{term Rep_three}}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   113
\put(70,25){\vector(-1,0){60}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   114
\put(25,26){\makebox(0,0)[bl]{@{term Abs_three}}}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   115
\end{picture}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   116
\end{center}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   117
Finally, \isacommand{typedef} asserts that @{term Rep_three} is
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   118
surjective on the subset @{term three} and @{term Abs_three} and @{term
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   119
Rep_three} are inverses of each other:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   120
\begin{center}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   121
\begin{tabular}{rl}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   122
@{thm Rep_three[no_vars]} &~~ (@{thm[source]Rep_three}) \\
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   123
@{thm Rep_three_inverse[no_vars]} &~~ (@{thm[source]Rep_three_inverse}) \\
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   124
@{thm Abs_three_inverse[no_vars]} &~~ (@{thm[source]Abs_three_inverse})
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   125
\end{tabular}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   126
\end{center}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   127
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   128
From the above example it should be clear what \isacommand{typedef} does
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   129
in general: simply replace the name @{text three} and the set
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   130
@{term"{n. n\<le>2}"} by the respective arguments.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   131
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   132
Our next step is to define the basic functions expected on the new type.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   133
Although this depends on the type at hand, the following strategy works well:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   134
\begin{itemize}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   135
\item define a small kernel of basic functions such that all further
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   136
functions you anticipate can be defined on top of that kernel.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   137
\item define the kernel in terms of corresponding functions on the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   138
representing type using @{term Abs} and @{term Rep} to convert between the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   139
two levels.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   140
\end{itemize}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   141
In our example it suffices to give the three elements of type @{typ three}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   142
names:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   143
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   144
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   145
constdefs
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   146
  A:: three
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   147
 "A \<equiv> Abs_three 0"
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   148
  B:: three
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   149
 "B \<equiv> Abs_three 1"
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   150
  C :: three
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   151
 "C \<equiv> Abs_three 2";
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   152
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   153
text{*
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   154
So far, everything was easy. But it is clear that reasoning about @{typ
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   155
three} will be hell if we have to go back to @{typ nat} every time. Thus our
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   156
aim must be to raise our level of abstraction by deriving enough theorems
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   157
about type @{typ three} to characterize it completely. And those theorems
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   158
should be phrased in terms of @{term A}, @{term B} and @{term C}, not @{term
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   159
Abs_three} and @{term Rep_three}. Because of the simplicity of the example,
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   160
we merely need to prove that @{term A}, @{term B} and @{term C} are distinct
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   161
and that they exhaust the type.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   162
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   163
We start with a helpful version of injectivity of @{term Abs_three} on the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   164
representing subset:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   165
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   166
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   167
lemma [simp]:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   168
 "\<lbrakk> x \<in> three; y \<in> three \<rbrakk> \<Longrightarrow> (Abs_three x = Abs_three y) = (x=y)";
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   169
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   170
txt{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   171
We prove both directions separately. From @{prop"Abs_three x = Abs_three y"}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   172
we derive @{prop"Rep_three(Abs_three x) = Rep_three(Abs_three y)"} (via
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   173
@{thm[source]arg_cong}: @{thm arg_cong}), and thus the required @{prop"x =
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   174
y"} by simplification with @{thm[source]Abs_three_inverse}. The other direction
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   175
is trivial by simplification:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   176
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   177
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   178
apply(rule iffI);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   179
 apply(drule_tac f = Rep_three in arg_cong);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   180
 apply(simp add:Abs_three_inverse);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   181
by simp;
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   182
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   183
text{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   184
Analogous lemmas can be proved in the same way for arbitrary type definitions.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   185
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   186
Distinctness of @{term A}, @{term B} and @{term C} follows immediately
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   187
if we expand their definitions and rewrite with the above simplification rule:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   188
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   189
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   190
lemma "A \<noteq> B \<and> B \<noteq> A \<and> A \<noteq> C \<and> C \<noteq> A \<and> B \<noteq> C \<and> C \<noteq> B";
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   191
by(simp add:A_def B_def C_def three_def);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   192
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   193
text{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   194
Of course we rely on the simplifier to solve goals like @{prop"0 \<noteq> 1"}.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   195
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   196
The fact that @{term A}, @{term B} and @{term C} exhaust type @{typ three} is
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   197
best phrased as a case distinction theorem: if you want to prove @{prop"P x"}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   198
(where @{term x} is of type @{typ three}) it suffices to prove @{prop"P A"},
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   199
@{prop"P B"} and @{prop"P C"}. First we prove the analogous proposition for the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   200
representation: *}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   201
10654
458068404143 *** empty log message ***
nipkow
parents: 10420
diff changeset
   202
lemma cases_lemma: "\<lbrakk> Q 0; Q 1; Q 2; n : three \<rbrakk> \<Longrightarrow>  Q n";
10366
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   203
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   204
txt{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   205
Expanding @{thm[source]three_def} yields the premise @{prop"n\<le>2"}. Repeated
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   206
elimination with @{thm[source]le_SucE}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   207
@{thm[display]le_SucE}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   208
reduces @{prop"n\<le>2"} to the three cases @{prop"n\<le>0"}, @{prop"n=1"} and
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   209
@{prop"n=2"} which are trivial for simplification:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   210
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   211
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   212
apply(simp add:three_def);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   213
apply((erule le_SucE)+);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   214
apply simp_all;
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   215
done
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   216
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   217
text{*
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   218
Now the case distinction lemma on type @{typ three} is easy to derive if you know how to:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   219
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   220
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   221
lemma three_cases: "\<lbrakk> P A; P B; P C \<rbrakk> \<Longrightarrow> P x";
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   222
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   223
txt{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   224
We start by replacing the @{term x} by @{term"Abs_three(Rep_three x)"}:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   225
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   226
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   227
apply(rule subst[OF Rep_three_inverse]);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   228
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   229
txt{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   230
This substitution step worked nicely because there was just a single
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   231
occurrence of a term of type @{typ three}, namely @{term x}.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   232
When we now apply the above lemma, @{term Q} becomes @{term"\<lambda>n. P(Abs_three
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   233
n)"} because @{term"Rep_three x"} is the only term of type @{typ nat}:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   234
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   235
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   236
apply(rule cases_lemma);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   237
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   238
txt{*
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   239
@{subgoals[display,indent=0]}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   240
The resulting subgoals are easily solved by simplification:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   241
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   242
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   243
apply(simp_all add:A_def B_def C_def Rep_three);
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   244
done
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   245
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   246
text{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   247
This concludes the derivation of the characteristic theorems for
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   248
type @{typ three}.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   249
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   250
The attentive reader has realized long ago that the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   251
above lengthy definition can be collapsed into one line:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   252
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   253
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   254
datatype three' = A | B | C;
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   255
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   256
text{*\noindent
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   257
In fact, the \isacommand{datatype} command performs internally more or less
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   258
the same derivations as we did, which gives you some idea what life would be
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   259
like without \isacommand{datatype}.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   260
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   261
Although @{typ three} could be defined in one line, we have chosen this
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   262
example to demonstrate \isacommand{typedef} because its simplicity makes the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   263
key concepts particularly easy to grasp. If you would like to see a
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   264
nontrivial example that cannot be defined more directly, we recommend the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   265
definition of \emph{finite multisets} in the HOL library.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   266
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   267
Let us conclude by summarizing the above procedure for defining a new type.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   268
Given some abstract axiomatic description $P$ of a type $ty$ in terms of a
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   269
set of functions $F$, this involves three steps:
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   270
\begin{enumerate}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   271
\item Find an appropriate type $\tau$ and subset $A$ which has the desired
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   272
  properties $P$, and make a type definition based on this representation.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   273
\item Define the required functions $F$ on $ty$ by lifting
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   274
analogous functions on the representation via $Abs_ty$ and $Rep_ty$.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   275
\item Prove that $P$ holds for $ty$ by lifting $P$ from the representation.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   276
\end{enumerate}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   277
You can now forget about the representation and work solely in terms of the
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   278
abstract functions $F$ and properties $P$.
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   279
*}
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   280
dd74d0a56df9 *** empty log message ***
nipkow
parents:
diff changeset
   281
(*<*)end(*>*)