doc-src/TutorialI/Datatype/ABexpr.thy
changeset 8745 13b32661dde4
child 8771 026f37a86ea7
equal deleted inserted replaced
8744:22fa8b16c3ae 8745:13b32661dde4
       
     1 (*<*)
       
     2 theory ABexpr = Main:;
       
     3 (*>*)
       
     4 
       
     5 text{*
       
     6 Sometimes it is necessary to define two datatypes that depend on each
       
     7 other. This is called \textbf{mutual recursion}. As an example consider a
       
     8 language of arithmetic and boolean expressions where
       
     9 \begin{itemize}
       
    10 \item arithmetic expressions contain boolean expressions because there are
       
    11   conditional arithmetic expressions like ``if $m<n$ then $n-m$ else $m-n$'',
       
    12   and
       
    13 \item boolean expressions contain arithmetic expressions because of
       
    14   comparisons like ``$m<n$''.
       
    15 \end{itemize}
       
    16 In Isabelle this becomes
       
    17 *}
       
    18 
       
    19 datatype 'a aexp = IF   "'a bexp" "'a aexp" "'a aexp"
       
    20                  | Sum  "'a aexp" "'a aexp"
       
    21                  | Diff "'a aexp" "'a aexp"
       
    22                  | Var 'a
       
    23                  | Num nat
       
    24 and      'a bexp = Less "'a aexp" "'a aexp"
       
    25                  | And  "'a bexp" "'a bexp"
       
    26                  | Neg  "'a bexp";
       
    27 
       
    28 text{*\noindent
       
    29 Type \isa{aexp} is similar to \isa{expr} in \S\ref{sec:ExprCompiler},
       
    30 except that we have fixed the values to be of type \isa{nat} and that we
       
    31 have fixed the two binary operations \isa{Sum} and \isa{Diff}. Boolean
       
    32 expressions can be arithmetic comparisons, conjunctions and negations.
       
    33 The semantics is fixed via two evaluation functions
       
    34 *}
       
    35 
       
    36 consts  evala :: "('a \\<Rightarrow> nat) \\<Rightarrow> 'a aexp \\<Rightarrow> nat"
       
    37         evalb :: "('a \\<Rightarrow> nat) \\<Rightarrow> 'a bexp \\<Rightarrow> bool";
       
    38 
       
    39 text{*\noindent
       
    40 that take an environment (a mapping from variables \isa{'a} to values
       
    41 \isa{nat}) and an expression and return its arithmetic/boolean
       
    42 value. Since the datatypes are mutually recursive, so are functions that
       
    43 operate on them. Hence they need to be defined in a single \isacommand{primrec}
       
    44 section:
       
    45 *}
       
    46 
       
    47 primrec
       
    48   "evala env (IF b a1 a2) =
       
    49      (if evalb env b then evala env a1 else evala env a2)"
       
    50   "evala env (Sum a1 a2) = evala env a1 + evala env a2"
       
    51   "evala env (Diff a1 a2) = evala env a1 - evala env a2"
       
    52   "evala env (Var v) = env v"
       
    53   "evala env (Num n) = n"
       
    54 
       
    55   "evalb env (Less a1 a2) = (evala env a1 < evala env a2)"
       
    56   "evalb env (And b1 b2) = (evalb env b1 \\<and> evalb env b2)"
       
    57   "evalb env (Neg b) = (\\<not> evalb env b)"
       
    58 
       
    59 text{*\noindent
       
    60 In the same fashion we also define two functions that perform substitution:
       
    61 *}
       
    62 
       
    63 consts substa :: "('a \\<Rightarrow> 'b aexp) \\<Rightarrow> 'a aexp \\<Rightarrow> 'b aexp"
       
    64        substb :: "('a \\<Rightarrow> 'b aexp) \\<Rightarrow> 'a bexp \\<Rightarrow> 'b bexp";
       
    65 
       
    66 text{*\noindent
       
    67 The first argument is a function mapping variables to expressions, the
       
    68 substitution. It is applied to all variables in the second argument. As a
       
    69 result, the type of variables in the expression may change from \isa{'a}
       
    70 to \isa{'b}. Note that there are only arithmetic and no boolean variables.
       
    71 *}
       
    72 
       
    73 primrec
       
    74   "substa s (IF b a1 a2) =
       
    75      IF (substb s b) (substa s a1) (substa s a2)"
       
    76   "substa s (Sum a1 a2) = Sum (substa s a1) (substa s a2)"
       
    77   "substa s (Diff a1 a2) = Diff (substa s a1) (substa s a2)"
       
    78   "substa s (Var v) = s v"
       
    79   "substa s (Num n) = Num n"
       
    80 
       
    81   "substb s (Less a1 a2) = Less (substa s a1) (substa s a2)"
       
    82   "substb s (And b1 b2) = And (substb s b1) (substb s b2)"
       
    83   "substb s (Neg b) = Neg (substb s b)";
       
    84 
       
    85 text{*
       
    86 Now we can prove a fundamental theorem about the interaction between
       
    87 evaluation and substitution: applying a substitution $s$ to an expression $a$
       
    88 and evaluating the result in an environment $env$ yields the same result as
       
    89 evaluation $a$ in the environment that maps every variable $x$ to the value
       
    90 of $s(x)$ under $env$. If you try to prove this separately for arithmetic or
       
    91 boolean expressions (by induction), you find that you always need the other
       
    92 theorem in the induction step. Therefore you need to state and prove both
       
    93 theorems simultaneously:
       
    94 *}
       
    95 
       
    96 lemma "evala env (substa s a) = evala (\\<lambda>x. evala env (s x)) a \\<and>
       
    97         evalb env (substb s b) = evalb (\\<lambda>x. evala env (s x)) b";
       
    98 apply(induct_tac a and b);
       
    99 
       
   100 txt{*\noindent
       
   101 The resulting 8 goals (one for each constructor) are proved in one fell swoop:
       
   102 *}
       
   103 
       
   104 apply auto.;
       
   105 
       
   106 text{*
       
   107 In general, given $n$ mutually recursive datatypes $\tau@1$, \dots, $\tau@n$,
       
   108 an inductive proof expects a goal of the form
       
   109 \[ P@1(x@1)\ \land \dots \land P@n(x@n) \]
       
   110 where each variable $x@i$ is of type $\tau@i$. Induction is started by
       
   111 \begin{ttbox}
       
   112 apply(induct_tac \(x@1\) \texttt{and} \(\dots\) \texttt{and} \(x@n\));
       
   113 \end{ttbox}
       
   114 
       
   115 \begin{exercise}
       
   116   Define a function \isa{norma} of type \isa{'a aexp \isasymFun\ 'a aexp} that
       
   117   replaces \isa{IF}s with complex boolean conditions by nested
       
   118   \isa{IF}s where each condition is a \isa{Less} --- \isa{And} and
       
   119   \isa{Neg} should be eliminated completely. Prove that \isa{norma}
       
   120   preserves the value of an expression and that the result of \isa{norma}
       
   121   is really normal, i.e.\ no more \isa{And}s and \isa{Neg}s occur in
       
   122   it.  ({\em Hint:} proceed as in \S\ref{sec:boolex}).
       
   123 \end{exercise}
       
   124 *}
       
   125 (*<*)
       
   126 end
       
   127 (*>*)