ProgTutorial/Tactical.thy
changeset 424 5e0a2b50707e
parent 422 e79563b14b0f
child 436 373f99b1221a
equal deleted inserted replaced
423:0a25b35178c3 424:5e0a2b50707e
  2260   conv ctrm
  2260   conv ctrm
  2261 end"
  2261 end"
  2262   "True \<or> P \<equiv> True \<or> P"}
  2262   "True \<or> P \<equiv> True \<or> P"}
  2263 
  2263 
  2264   Rewriting with more than one theorem can be done using the function 
  2264   Rewriting with more than one theorem can be done using the function 
  2265   @{ML_ind rewrs_conv in More_Conv} from the structure @{ML_struct More_Conv}.
  2265   @{ML_ind rewrs_conv in Conv} from the structure @{ML_struct Conv}.
  2266   
  2266   
  2267 
  2267 
  2268   Apart from the function @{ML beta_conversion in Thm}, which is able to fully
  2268   Apart from the function @{ML beta_conversion in Thm}, which is able to fully
  2269   beta-normalise a term, the conversions so far are restricted in that they
  2269   beta-normalise a term, the conversions so far are restricted in that they
  2270   only apply to the outer-most level of a @{ML_type cterm}. In what follows we
  2270   only apply to the outer-most level of a @{ML_type cterm}. In what follows we
  2343 *}
  2343 *}
  2344 
  2344 
  2345 text {*
  2345 text {*
  2346   Conversions that traverse terms, like @{ML true_conj1_conv} above, can be
  2346   Conversions that traverse terms, like @{ML true_conj1_conv} above, can be
  2347   implemented more succinctly with the combinators @{ML_ind bottom_conv in
  2347   implemented more succinctly with the combinators @{ML_ind bottom_conv in
  2348   More_Conv} and @{ML_ind top_conv in More_Conv}. For example:
  2348   Conv} and @{ML_ind top_conv in Conv}. For example:
  2349 *}
  2349 *}
  2350 
  2350 
  2351 ML{*fun true_conj1_conv ctxt =
  2351 ML{*fun true_conj1_conv ctxt =
  2352 let
  2352 let
  2353   val conv = Conv.try_conv (Conv.rewr_conv @{thm true_conj1})
  2353   val conv = Conv.try_conv (Conv.rewr_conv @{thm true_conj1})
  2354 in
  2354 in
  2355   More_Conv.bottom_conv (K conv) ctxt
  2355   Conv.bottom_conv (K conv) ctxt
  2356 end*}
  2356 end*}
  2357 
  2357 
  2358 text {*
  2358 text {*
  2359   If we regard terms as trees with variables and constants on the top, then 
  2359   If we regard terms as trees with variables and constants on the top, then 
  2360   @{ML bottom_conv in More_Conv} traverses first the the term and
  2360   @{ML bottom_conv in Conv} traverses first the the term and
  2361   on the ``way down'' applies the conversion, whereas @{ML top_conv in
  2361   on the ``way down'' applies the conversion, whereas @{ML top_conv in
  2362   More_Conv} applies the conversion on the ``way up''. To see the difference, 
  2362   Conv} applies the conversion on the ``way up''. To see the difference, 
  2363   assume the following two meta-equations
  2363   assume the following two meta-equations
  2364 *}
  2364 *}
  2365 
  2365 
  2366 lemma conj_assoc:
  2366 lemma conj_assoc:
  2367   fixes A B C::bool
  2367   fixes A B C::bool
  2376   two results are calculated. 
  2376   two results are calculated. 
  2377 
  2377 
  2378   @{ML_response_fake [display, gray]
  2378   @{ML_response_fake [display, gray]
  2379   "let
  2379   "let
  2380   val ctxt = @{context}
  2380   val ctxt = @{context}
  2381   val conv = Conv.try_conv (More_Conv.rewrs_conv @{thms conj_assoc})
  2381   val conv = Conv.try_conv (Conv.rewrs_conv @{thms conj_assoc})
  2382   val conv_top = More_Conv.top_conv (K conv) ctxt
  2382   val conv_top = Conv.top_conv (K conv) ctxt
  2383   val conv_bot = More_Conv.bottom_conv (K conv) ctxt
  2383   val conv_bot = Conv.bottom_conv (K conv) ctxt
  2384   val ctrm = @{cterm \"(a \<and> (b \<and> c)) \<and> d\"}
  2384   val ctrm = @{cterm \"(a \<and> (b \<and> c)) \<and> d\"}
  2385 in
  2385 in
  2386   (conv_top ctrm, conv_bot ctrm)
  2386   (conv_top ctrm, conv_bot ctrm)
  2387 end"
  2387 end"
  2388   "(\"(a \<and> (b \<and> c)) \<and> d \<equiv> a \<and> (b \<and> (c \<and> d))\",
  2388   "(\"(a \<and> (b \<and> c)) \<and> d \<equiv> a \<and> (b \<and> (c \<and> d))\",
  2398   case Thm.term_of ctrm of
  2398   case Thm.term_of ctrm of
  2399     Const (@{const_name If}, _) $ _ =>
  2399     Const (@{const_name If}, _) $ _ =>
  2400       Conv.arg_conv (true_conj1_conv ctxt) ctrm
  2400       Conv.arg_conv (true_conj1_conv ctxt) ctrm
  2401   | _ => Conv.no_conv ctrm 
  2401   | _ => Conv.no_conv ctrm 
  2402 
  2402 
  2403 val if_true1_conv = More_Conv.top_sweep_conv if_true1_simple_conv*}
  2403 val if_true1_conv = Conv.top_sweep_conv if_true1_simple_conv*}
  2404 
  2404 
  2405 text {*
  2405 text {*
  2406   In the first function we only treat the top-most redex and also only the
  2406   In the first function we only treat the top-most redex and also only the
  2407   success case. As default we return @{ML no_conv in Conv}.  To apply this
  2407   success case. As default we return @{ML no_conv in Conv}.  To apply this
  2408   ``simple'' conversion inside a term, we use in the last line the combinator @{ML_ind
  2408   ``simple'' conversion inside a term, we use in the last line the combinator @{ML_ind
  2409   top_sweep_conv in More_Conv}, which traverses the term starting from the
  2409   top_sweep_conv in Conv}, which traverses the term starting from the
  2410   root and applies it to all the redexes on the way, but stops in each branch as
  2410   root and applies it to all the redexes on the way, but stops in each branch as
  2411   soon as it found one redex. Here is an example for this conversion:
  2411   soon as it found one redex. Here is an example for this conversion:
  2412 
  2412 
  2413 
  2413 
  2414   @{ML_response_fake [display,gray]
  2414   @{ML_response_fake [display,gray]
  2494 
  2494 
  2495 text {*
  2495 text {*
  2496   As you can see, the premises are rewritten according to @{ML if_true1_conv}, while
  2496   As you can see, the premises are rewritten according to @{ML if_true1_conv}, while
  2497   the conclusion according to @{ML true_conj1_conv}. If we only have one
  2497   the conclusion according to @{ML true_conj1_conv}. If we only have one
  2498   conversion that should be uniformly applied to the whole goal state, we
  2498   conversion that should be uniformly applied to the whole goal state, we
  2499   can simplify @{ML true1_tac} using @{ML_ind top_conv in More_Conv}.
  2499   can simplify @{ML true1_tac} using @{ML_ind top_conv in Conv}.
  2500 
  2500 
  2501   Conversions are also be helpful for constructing meta-equality theorems.
  2501   Conversions are also be helpful for constructing meta-equality theorems.
  2502   Such theorems are often definitions. As an example consider the following
  2502   Such theorems are often definitions. As an example consider the following
  2503   two ways of defining the identity function in Isabelle. 
  2503   two ways of defining the identity function in Isabelle. 
  2504 *}
  2504 *}
  2590   have to construct quite large terms. Also see Recipe \ref{rec:timing} for information 
  2590   have to construct quite large terms. Also see Recipe \ref{rec:timing} for information 
  2591   about timing.
  2591   about timing.
  2592   \end{exercise}
  2592   \end{exercise}
  2593 
  2593 
  2594   \begin{readmore}
  2594   \begin{readmore}
  2595   See @{ML_file "Pure/conv.ML"} and  @{ML_file "Tools/more_conv.ML"}
  2595   See @{ML_file "Pure/conv.ML"}
  2596   for more information about conversion combinators. 
  2596   for more information about conversion combinators. 
  2597   Some basic conversions are defined in  @{ML_file "Pure/thm.ML"},
  2597   Some basic conversions are defined in  @{ML_file "Pure/thm.ML"},
  2598   @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}.
  2598   @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}.
  2599   \end{readmore}
  2599   \end{readmore}
  2600 
  2600