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 |