|   1374   Thm.beta_conversion false (Thm.capply add two) |   1394   Thm.beta_conversion false (Thm.capply add two) | 
|   1375 end" |   1395 end" | 
|   1376   "((\<lambda>x y. x + y) 2) \<equiv> \<lambda>y. 2 + y"}  |   1396   "((\<lambda>x y. x + y) 2) \<equiv> \<lambda>y. 2 + y"}  | 
|   1377  |   1397  | 
|   1378   Again, we actually see as output only the fully normalised term  |   1398   Again, we actually see as output only the fully normalised term  | 
|   1379   @{term "\<lambda>y. 2 + y"}. |   1399   @{text "\<lambda>y. 2 + y"}. | 
|   1380  |   1400  | 
|   1381   The main point of conversions is that they can be used for rewriting terms. |   1401   The main point of conversions is that they can be used for rewriting | 
|   1382   For this you can use the function @{ML "Conv.rewr_conv"}. Suppose we want  |   1402   @{ML_type cterm}s. To do this you can use the function @{ML | 
|   1383   to rewrite a term according to the (meta)equation: |   1403   "Conv.rewr_conv"} which expects a meta-equation as an argument. Suppose we | 
|   1384  |   1404   want to rewrite a @{ML_type cterm} according to the (meta)equation: | 
|   1385 *} |   1405 *} | 
|   1386  |   1406  | 
|   1387 lemma true_conj1: "True \<and> P \<equiv> P" by simp |   1407 lemma true_conj1: "True \<and> P \<equiv> P" by simp | 
|   1388  |   1408  | 
|   1389 text {*  |   1409 text {*  | 
|   1390   then we can use it in order to rewrite @{term "True \<and> (Foo \<longrightarrow> Bar)"}: |   1410   You can see how this function works with the example  | 
|         |   1411   @{term "True \<and> (Foo \<longrightarrow> Bar)"}: | 
|   1391  |   1412  | 
|   1392   @{ML_response_fake [display,gray] |   1413   @{ML_response_fake [display,gray] | 
|   1393 "let  |   1414 "let  | 
|   1394   val ctrm =  @{cterm \"True \<and> (Foo \<longrightarrow> Bar)\"} |   1415   val ctrm =  @{cterm \"True \<and> (Foo \<longrightarrow> Bar)\"} | 
|   1395 in |   1416 in | 
|   1396   Conv.rewr_conv @{thm true_conj1} ctrm |   1417   Conv.rewr_conv @{thm true_conj1} ctrm | 
|   1397 end" |   1418 end" | 
|   1398   "True \<and> (Foo \<longrightarrow> Bar) \<equiv> Foo \<longrightarrow> Bar"} |   1419   "True \<and> (Foo \<longrightarrow> Bar) \<equiv> Foo \<longrightarrow> Bar"} | 
|   1399  |   1420  | 
|   1400   The function @{ML Conv.rewr_conv} only does rewriting on the outer-most |   1421   Note, however, that the function @{ML Conv.rewr_conv} only rewrites the  | 
|   1401   level, otherwise it raises the exception @{ML CTERM}. |   1422   outer-most level of the @{ML_type cterm}. If the given @{ML_type cterm} does not match the  | 
|         |   1423   left-hand side of the theorem, then  @{ML Conv.rewr_conv} raises  | 
|         |   1424   the exception @{ML CTERM}. | 
|   1402  |   1425  | 
|   1403   This very primitive way of rewriting can be made more powerful by |   1426   This very primitive way of rewriting can be made more powerful by | 
|   1404   combining several conversions into one. For this you can use conversion |   1427   combining several conversions into one. For this you can use conversion | 
|   1405   combinators. The simplest conversion combinator is @{ML then_conv},  |   1428   combinators. The simplest conversion combinator is @{ML then_conv},  | 
|   1406   which applies one conversion after another. For example |   1429   which applies one conversion after another. For example | 
|   1407  |   1430  | 
|   1408   @{ML_response_fake [display,gray] |   1431   @{ML_response_fake [display,gray] | 
|   1409 "let |   1432 "let | 
|   1410   val conv1 = Thm.beta_conversion true |   1433   val conv1 = Thm.beta_conversion false | 
|   1411   val conv2 = Conv.rewr_conv @{thm true_conj1} |   1434   val conv2 = Conv.rewr_conv @{thm true_conj1} | 
|   1412   val ctrm = Thm.capply (@{cterm \"\<lambda>x. x \<and> False\"}) (@{cterm \"True\"}) |   1435   val ctrm = Thm.capply @{cterm \"\<lambda>x. x \<and> False\"} @{cterm \"True\"} | 
|   1413 in |   1436 in | 
|   1414   (conv1 then_conv conv2) ctrm |   1437   (conv1 then_conv conv2) ctrm | 
|   1415 end" |   1438 end" | 
|   1416   "(\<lambda>x. x \<and> False) True \<equiv> False"} |   1439   "(\<lambda>x. x \<and> False) True \<equiv> False"} | 
|   1417  |   1440  | 
|         |   1441   where we first beta-reduce the term and then rewrite according to | 
|         |   1442   @{thm [source] true_conj1}.  | 
|         |   1443  | 
|   1418   The conversion combinator @{ML else_conv} tries out the  |   1444   The conversion combinator @{ML else_conv} tries out the  | 
|   1419   first one, and if it does not apply, tries the second. For example  |   1445   first one, and if it does not apply, tries the second. For example  | 
|   1420  |   1446  | 
|   1421   @{ML_response_fake [display,gray] |   1447   @{ML_response_fake [display,gray] | 
|   1422 "let |   1448 "let | 
|   1423   val conv = Conv.rewr_conv @{thm true_conj1}  |   1449   val conv = Conv.rewr_conv @{thm true_conj1} else_conv Conv.all_conv | 
|   1424              else_conv Conv.all_conv |         | 
|   1425   val ctrm1 = @{cterm \"True \<and> Q\"} |   1450   val ctrm1 = @{cterm \"True \<and> Q\"} | 
|   1426   val ctrm2 = @{cterm \"P \<or> (True \<and> Q)\"} |   1451   val ctrm2 = @{cterm \"P \<or> (True \<and> Q)\"} | 
|   1427 in |   1452 in | 
|   1428   (conv ctrm1, conv ctrm2) |   1453   (conv ctrm1, conv ctrm2) | 
|   1429 end" |   1454 end" | 
|   1430 "(True \<and> Q \<equiv> Q,  |   1455 "(True \<and> Q \<equiv> Q, P \<or> True \<and> Q \<equiv> P \<or> True \<and> Q)"} | 
|   1431  P \<or> True \<and> Q \<equiv> P \<or> True \<and> Q)"} |         | 
|   1432  |   1456  | 
|   1433   Here the conversion of @{thm [source] true_conj1} only applies |   1457   Here the conversion of @{thm [source] true_conj1} only applies | 
|   1434   in the first case, but fails in the second. The whole conversion |   1458   in the first case, but fails in the second. The whole conversion | 
|   1435   does not fail because the combinator @{ML else_conv} will then  |   1459   does not fail, however, because the combinator @{ML else_conv} will then  | 
|   1436   try out @{ML Conv.all_conv}, which allways succeeds. |   1460   try out @{ML Conv.all_conv}, which always succeeds. | 
|   1437  |   1461  | 
|   1438   The combinator @{ML Conv.arg_conv} will apply the conversion on |   1462   Apart from the function @{ML beta_conversion in Thm}, which able to fully | 
|   1439   the first argument, taht is the term must be of the form  |   1463   beta-normalise a term, the restriction of conversions so far is that they | 
|   1440   @{ML "t1 $ t2" for t1 t2} and the conversion is applied to @{text t2}. |   1464   only apply to the outer-most level of a @{ML_type cterm}. In what follows we | 
|   1441   For example |   1465   will lift this restriction. The combinator @{ML Conv.arg_conv} will apply | 
|         |   1466   the conversion on the first argument of an application, that is the term | 
|         |   1467   must be of the form @{ML "t1 $ t2" for t1 t2} and the conversion is applied | 
|         |   1468   to @{text t2}.  For example | 
|   1442  |   1469  | 
|   1443   @{ML_response_fake [display,gray] |   1470   @{ML_response_fake [display,gray] | 
|   1444 "let  |   1471 "let  | 
|   1445   val conv = Conv.rewr_conv @{thm true_conj1} |   1472   val conv = Conv.rewr_conv @{thm true_conj1} | 
|   1446   val ctrm = @{cterm \"P \<or> (True \<and> Q)\"} |   1473   val ctrm = @{cterm \"P \<or> (True \<and> Q)\"} | 
|   1447 in |   1474 in | 
|   1448   Conv.arg_conv conv ctrm |   1475   Conv.arg_conv conv ctrm | 
|   1449 end" |   1476 end" | 
|   1450 "P \<or> (True \<and> Q) \<equiv> P \<or> Q"} |   1477 "P \<or> (True \<and> Q) \<equiv> P \<or> Q"} | 
|   1451  |   1478  | 
|   1452   The reason for this behaviour is that @{text "(op \<or>)"} expects two arguments |   1479   The reason for this behaviour is that @{text "(op \<or>)"} expects two | 
|   1453   and so is of the form @{text "Const \<dots> $ t1 $ t2"}. The conversion is then  |   1480   arguments.  So the term must be of the form @{text "Const \<dots> $ t1 $ t2"}. The | 
|   1454   applied to @{text "t2"} which stands for @{term "True \<and> Q"}. |   1481   conversion is then applied to @{text "t2"} which in the example above | 
|   1455  |   1482   stands for @{term "True \<and> Q"}. | 
|   1456 *} |   1483  | 
|   1457  |   1484   The function @{ML Conv.abs_conv} applies a conversion under an abstractions. | 
|   1458  |   1485   For example: | 
|   1459 text {* |   1486  | 
|   1460   To begin with, let us assumes we want to simplify with the rewrite rule |   1487   @{ML_response_fake [display,gray] | 
|   1461   @{text true_conj1}. As a conversion, this may look as follows: |   1488 "let  | 
|   1462 *} |   1489   val conv = K (Conv.rewr_conv @{thm true_conj1})  | 
|   1463  |   1490   val ctrm = @{cterm \"\<lambda>P. True \<and> P \<and> Foo\"} | 
|   1464  |   1491 in | 
|   1465 ML{*fun all_true1_conv ctxt ct = |   1492   Conv.abs_conv conv @{context} ctrm | 
|   1466   (case Thm.term_of ct of |   1493 end" | 
|         |   1494   "\<lambda>P. True \<and> P \<and> Foo \<equiv> \<lambda>P. P \<and> Foo"} | 
|         |   1495    | 
|         |   1496   The conversion that goes under an application is | 
|         |   1497   @{ML Conv.combination_conv}. It expects two conversions, which each of them | 
|         |   1498   is applied to the corresponding ``branch'' of the application.  | 
|         |   1499  | 
|         |   1500   We can now apply all these functions in a | 
|         |   1501   conversion that recursively descends a term and applies a conversion in all | 
|         |   1502   possible positions. | 
|         |   1503 *} | 
|         |   1504  | 
|         |   1505 ML %linenosgray{*fun all_true1_conv ctxt ctrm = | 
|         |   1506   case (Thm.term_of ctrm) of | 
|   1467     @{term "op \<and>"} $ @{term True} $ _ =>  |   1507     @{term "op \<and>"} $ @{term True} $ _ =>  | 
|   1468       (Conv.arg_conv (all_true1_conv ctxt) then_conv |   1508       (Conv.arg_conv (all_true1_conv ctxt) then_conv | 
|   1469         Conv.rewr_conv @{thm true_conj1}) ct |   1509          Conv.rewr_conv @{thm true_conj1}) ctrm | 
|   1470   | _ $ _ => Conv.combination_conv (all_true1_conv ctxt) |   1510   | _ $ _ => Conv.combination_conv  | 
|   1471       (all_true1_conv ctxt) ct |   1511                  (all_true1_conv ctxt) (all_true1_conv ctxt) ctrm | 
|   1472   | Abs _ => Conv.abs_conv (fn (_, cx) => all_true1_conv cx) ctxt ct |   1512   | Abs _ => Conv.abs_conv (fn (_, ctxt) => all_true1_conv ctxt) ctxt ctrm | 
|   1473   | _ => Conv.all_conv ct)*} |   1513   | _ => Conv.all_conv ctrm*} | 
|   1474  |   1514  | 
|   1475 text {* |   1515 text {* | 
|   1476   Here is this conversion in action: |   1516   This functions descends under applications (Line 6 and 7) and abstractions  | 
|         |   1517   (Line 8); and ``fires'' if the outer-most constant is an @{text "True \<and> \<dots>"} | 
|         |   1518   (Lines 3-5); otherwise it leaves the term unchanged (Line 9). To see this  | 
|         |   1519   conversion in action, consider the following example. | 
|         |   1520  | 
|         |   1521 @{ML_response_fake [display,gray] | 
|         |   1522 "let | 
|         |   1523   val ctxt = @{context} | 
|         |   1524   val ctrm = @{cterm \"distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x\"} | 
|         |   1525 in | 
|         |   1526   all_true1_conv ctxt ctrm | 
|         |   1527 end" | 
|         |   1528   "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x \<equiv> distinct [1, x] \<longrightarrow> 1 \<noteq> x"} | 
|         |   1529  | 
|         |   1530   To see how much control you have about rewriting via conversions, let us  | 
|         |   1531   make the task a bit more complicated by rewriting according to the rule | 
|         |   1532   @{text true_conj1}, but only in the first arguments of @{term If}s. The  | 
|         |   1533   the conversion should be as follows. | 
|         |   1534 *} | 
|         |   1535  | 
|         |   1536 ML{*fun if_true1_conv ctxt ctrm = | 
|         |   1537   case Thm.term_of ctrm of | 
|         |   1538     Const (@{const_name If}, _) $ _ => | 
|         |   1539       Conv.arg_conv (all_true1_conv ctxt) ctrm | 
|         |   1540   | _ $ _ => Conv.combination_conv  | 
|         |   1541                         (if_true1_conv ctxt) (if_true1_conv ctxt) ctrm | 
|         |   1542   | Abs _ => Conv.abs_conv (fn (_, ctxt) => if_true1_conv ctxt) ctxt ctrm | 
|         |   1543   | _ => Conv.all_conv ctrm *} | 
|         |   1544  | 
|         |   1545 text {* | 
|         |   1546   Here is an application of this conversion: | 
|   1477  |   1547  | 
|   1478   @{ML_response_fake [display,gray] |   1548   @{ML_response_fake [display,gray] | 
|   1479   "all_true1_conv @{context} |   1549 "let | 
|   1480   @{cterm \"distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x\"}" |   1550   val ctxt = @{context} | 
|   1481   "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x \<equiv> distinct [1, x] \<longrightarrow> 1 \<noteq> x"} |   1551   val ctrm =  | 
|   1482  |   1552      @{cterm \"if P (True \<and> 1 \<noteq> 2) then True \<and> True else True \<and> False\"} | 
|   1483   Now, let us make the task a bit more complicated by rewriting according to the rule |   1553 in | 
|   1484   @{text true_conj1}, but only in the first arguments of @{term If}: |   1554   if_true1_conv ctxt ctrm | 
|   1485 *} |   1555 end" | 
|   1486  |   1556 "if P (True \<and> 1 \<noteq> 2) then True \<and> True else True \<and> False  | 
|   1487 ML{*fun if_true1_conv ctxt ct = |   1557 \<equiv> if P (1 \<noteq> 2) then True \<and> True else True \<and> False"} | 
|   1488   (case Thm.term_of ct of |   1558 *} | 
|   1489     Const (@{const_name If}, _) $ _ => |   1559  | 
|   1490       Conv.arg_conv (all_true1_conv ctxt) ct |   1560 text {* | 
|   1491   | _ $ _ => Conv.combination_conv (if_true1_conv ctxt) |   1561   So far we only applied conversions to @{ML_type cterm}s. Conversions can, however,  | 
|   1492       (if_true1_conv ctxt) ct |   1562   also work on theorems using the function @{ML "Conv.fconv_rule"}. As an example,  | 
|   1493   | Abs _ => Conv.abs_conv (fn (_, cx) => if_true1_conv cx) ctxt ct |   1563   consider @{ML all_true1_conv} and the lemma: | 
|   1494   | _ => Conv.all_conv ct)*} |   1564 *} | 
|   1495  |   1565  | 
|   1496 text {* |   1566 lemma foo_test: "P \<or> (True \<and> \<not>P)" by simp | 
|   1497   Here is an application of this conversion: |   1567  | 
|         |   1568 text {* | 
|         |   1569   Using the conversion you can transform this theorem into a new theorem | 
|         |   1570   as follows | 
|   1498  |   1571  | 
|   1499   @{ML_response_fake [display,gray] |   1572   @{ML_response_fake [display,gray] | 
|   1500   "if_true1_conv @{context} |   1573   "Conv.fconv_rule (all_true1_conv @{context}) @{thm foo_test}"  | 
|   1501   @{cterm \"if P (True \<and> 1 \<noteq> 2) then True \<and> True else True \<and> False\"}" |   1574   "?P \<or> \<not> ?P"} | 
|   1502   "if P (True \<and> 1 \<noteq> 2) then True \<and> True else True \<and> False \<equiv> if P (1 \<noteq> 2) then True \<and> True else True \<and> False"} |   1575  | 
|   1503 *} |   1576   Finally, conversions can also be turned into tactics and then applied to | 
|   1504  |   1577   goal states. This can be done with the help of the function @{ML CONVERSION}, | 
|   1505 text {* |   1578   and also some predefined conversion combinator which traverse a goal | 
|   1506   Conversions can also be turned into a tactic with the @{ML CONVERSION} |   1579   state. The combinators for the goal state are: @{ML Conv.params_conv} for | 
|   1507   tactical, and there are predefined conversionals to traverse a goal state. |   1580   going under parameters (i.e.~where goals are of the form @{text "\<And>x. P \<Longrightarrow> | 
|   1508   Given a state @{term "\<And>x. P \<Longrightarrow> Q"},  the conversional |   1581   Q"}); the function @{ML Conv.prems_conv} for applying the conversion to all | 
|   1509   @{ML Conv.params_conv} applies a conversion to @{term "P \<Longrightarrow> Q"}; |   1582   premises of a goal, and @{ML Conv.concl_conv} for applying the conversion to | 
|   1510   given a state @{term "\<lbrakk> P1; P2 \<rbrakk> \<Longrightarrow> Q"}, |   1583   the conclusion of a goal. | 
|   1511   the conversional @{ML Conv.prems_conv} applies a conversion to the premises |         | 
|   1512   @{term P1} and @{term P2}, and @{ML Conv.concl_conv} applies a conversion to |         | 
|   1513   the conclusion @{term Q}. |         | 
|   1514  |   1584  | 
|   1515   Assume we want to apply @{ML all_true1_conv} only in the conclusion |   1585   Assume we want to apply @{ML all_true1_conv} only in the conclusion | 
|   1516   of the goal, and @{ML if_true1_conv} should only be applied in the premises. |   1586   of the goal, and @{ML if_true1_conv} should only be applied in the premises. | 
|   1517   Here is a tactic doing exactly that: |   1587   Here is a tactic doing exactly that: | 
|   1518 *} |   1588 *} | 
|   1519  |   1589  | 
|   1520 ML{*val true1_tac = CSUBGOAL (fn (goal, i) => |   1590 ML{*val true1_tac = CSUBGOAL (fn (goal, i) => | 
|   1521   let val ctxt = ProofContext.init (Thm.theory_of_cterm goal) |   1591   let  | 
|         |   1592     val ctxt = ProofContext.init (Thm.theory_of_cterm goal) | 
|   1522   in |   1593   in | 
|   1523     CONVERSION ( |   1594     CONVERSION  | 
|   1524       Conv.params_conv ~1 (fn cx => |   1595       (Conv.params_conv ~1 (fn ctxt => | 
|   1525         (Conv.prems_conv ~1 (if_true1_conv cx)) then_conv |   1596         (Conv.prems_conv ~1 (if_true1_conv ctxt)) then_conv | 
|   1526           Conv.concl_conv ~1 (all_true1_conv cx)) ctxt) i |   1597           Conv.concl_conv ~1 (all_true1_conv ctxt)) ctxt) i | 
|   1527   end)*} |   1598   end)*} | 
|   1528  |   1599  | 
|   1529 text {*  |   1600 text {*  | 
|   1530   To demonstrate this tactic, consider the following example: |   1601   We call the conversions with the argument @{ML "~1"} in order to  | 
|         |   1602   analyse all parameters, premises and conclusions. If we call it with  | 
|         |   1603   a non-negative number, say @{text n}, then these conversions will  | 
|         |   1604   only be called on @{text n} premises (similar for parameters and | 
|         |   1605   conclusions). To test the tactic, consider the proof | 
|   1531 *} |   1606 *} | 
|   1532  |   1607  | 
|   1533 lemma |   1608 lemma | 
|   1534   "if True \<and> P then P else True \<and> False \<Longrightarrow> |   1609   "if True \<and> P then P else True \<and> False \<Longrightarrow> | 
|   1535   (if True \<and> Q then Q else P) \<longrightarrow> True \<and> (True \<and> Q)" |   1610   (if True \<and> Q then Q else P) \<longrightarrow> True \<and> (True \<and> Q)" | 
|   1536 apply(tactic {* true1_tac 1 *}) |   1611 apply(tactic {* true1_tac 1 *}) | 
|   1537 txt {* \begin{minipage}{\textwidth} |   1612 txt {* where the tactic yields the goal state | 
|         |   1613  | 
|         |   1614        \begin{minipage}{\textwidth} | 
|   1538        @{subgoals [display]}  |   1615        @{subgoals [display]}  | 
|   1539        \end{minipage} *} |   1616        \end{minipage} *} | 
|   1540 (*<*)oops(*>*) |   1617 (*<*)oops(*>*) | 
|   1541  |   1618  | 
|   1542 text {* |   1619 text {* | 
|   1543   Conversions are not restricted to work on certified terms only, they can also |   1620   To sum up this section, conversions are not as powerful as the simplifier | 
|   1544   be lifted to theorem transformers, i.e. functions mapping a theorem to a |   1621   and simprocs; the advantage of conversions, however, is that you never have | 
|   1545   theorem, by the help of @{ML Conv.fconv_rule}. As an example, consider the |   1622   to worry about non-termination. | 
|   1546   conversion @{ML all_true1_conv} again: |         | 
|   1547  |         | 
|   1548   @{ML_response_fake [display,gray] |         | 
|   1549   "Conv.fconv_rule (all_true1_conv @{context}) @{lemma \"P \<or> (True \<and> \<not>P)\" by simp}"  |         | 
|   1550   "P \<or> \<not>P"} |         | 
|   1551  |   1623  | 
|   1552   \begin{readmore} |   1624   \begin{readmore} | 
|   1553   See @{ML_file "Pure/conv.ML"} for more information about conversion combinators.  |   1625   See @{ML_file "Pure/conv.ML"} for more information about conversion combinators.  | 
|   1554   Further conversions are defined in  @{ML_file "Pure/thm.ML"}, |   1626   Further conversions are defined in  @{ML_file "Pure/thm.ML"}, | 
|   1555   @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}. |   1627   @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}. |