CookBook/Tactical.thy
changeset 146 4aa8a80e37ff
parent 145 f1ba430a5e7d
child 147 6dafb0815ae6
equal deleted inserted replaced
145:f1ba430a5e7d 146:4aa8a80e37ff
  1115   We can turn this function into a proper simproc using
  1115   We can turn this function into a proper simproc using
  1116 *}
  1116 *}
  1117 
  1117 
  1118 
  1118 
  1119 ML{*val fail_sp' = 
  1119 ML{*val fail_sp' = 
  1120   let 
  1120 let 
  1121     val thy = @{theory}
  1121   val thy = @{theory}
  1122     val pat = [@{term "Suc n"}]
  1122   val pat = [@{term "Suc n"}]
  1123   in
  1123 in
  1124     Simplifier.simproc_i thy "fail_sp'" pat (K fail_sp_aux')
  1124   Simplifier.simproc_i thy "fail_sp'" pat (K fail_sp_aux')
  1125   end*}
  1125 end*}
  1126 
  1126 
  1127 text {*
  1127 text {*
  1128   Here the pattern is given as @{ML_type term} (instead of @{ML_type cterm}).
  1128   Here the pattern is given as @{ML_type term} (instead of @{ML_type cterm}).
  1129   The function also takes a list of patterns that can trigger the simproc.
  1129   The function also takes a list of patterns that can trigger the simproc.
  1130   Now the simproc is set up and can be explicitly added using
  1130   Now the simproc is set up and can be explicitly added using
  1171 text {*
  1171 text {*
  1172   and set up the simproc as follows.
  1172   and set up the simproc as follows.
  1173 *}
  1173 *}
  1174 
  1174 
  1175 ML{*val plus_one_sp =
  1175 ML{*val plus_one_sp =
  1176   let
  1176 let
  1177     val thy = @{theory}
  1177   val thy = @{theory}
  1178     val pat = [@{term "Suc n"}] 
  1178   val pat = [@{term "Suc n"}] 
  1179   in
  1179 in
  1180     Simplifier.simproc_i thy "sproc +1" pat (K plus_one_sp_aux)
  1180   Simplifier.simproc_i thy "sproc +1" pat (K plus_one_sp_aux)
  1181   end*}
  1181 end*}
  1182 
  1182 
  1183 text {*
  1183 text {*
  1184   Now the simproc is set up so that it is triggered by terms
  1184   Now the simproc is set up so that it is triggered by terms
  1185   of the form @{term "Suc n"}, but inside the simproc we only produce
  1185   of the form @{term "Suc n"}, but inside the simproc we only produce
  1186   a theorem if the term is not @{term "Suc 0"}. The result you can see
  1186   a theorem if the term is not @{term "Suc 0"}. The result you can see
  1318 section {* Conversions\label{sec:conversion} *}
  1318 section {* Conversions\label{sec:conversion} *}
  1319 
  1319 
  1320 text {*
  1320 text {*
  1321 
  1321 
  1322   Conversions are a ``thin'' layer on top of Isabelle's inference kernel, and 
  1322   Conversions are a ``thin'' layer on top of Isabelle's inference kernel, and 
  1323   may be seen as a controllable, bare-bone version of Isabelle's simplifier.
  1323   can be viewed be as a controllable, bare-bone version of Isabelle's simplifier.
  1324   They are meta-equalities depending on some input term. Their type is
  1324   A difference is that conversions simplify @{ML_type cterm}s, while teh simplifier
  1325   as follows:
  1325   acts on theorems. The type for conversions is
  1326 *}
  1326 *}
  1327 
  1327 
  1328 ML{*type conv = Thm.cterm -> Thm.thm*}
  1328 ML{*type conv = Thm.cterm -> Thm.thm*}
  1329 
  1329 
  1330 text {*
  1330 text {*
  1331   The simplest two conversions are @{ML "Conv.all_conv"}, which maps a 
  1331   whereby the theorem is always a meta-equality. A simple conversion is 
  1332   term to an instance of the reflexivity theorem, and 
  1332   the function @{ML "Conv.all_conv"}, which maps a @{ML_type cterm} to an instance of 
  1333   @{ML "Conv.no_conv"}, which always fails:
  1333   the (meta)reflexivity theorem. For example:
  1334 
  1334 
  1335   @{ML_response_fake [display,gray]
  1335   @{ML_response_fake [display,gray]
  1336   "Conv.all_conv @{cterm True}" "True \<equiv> True"}
  1336   "Conv.all_conv @{cterm \"Foo \<or> Bar\"}"
       
  1337   "Foo \<or> Bar \<equiv> Foo \<or> Bar"}
       
  1338 
       
  1339   Another simple conversion is @{ML Conv.no_conv} which always raises the exception @{ML CTERM}
  1337 
  1340 
  1338   @{ML_response_fake [display,gray]
  1341   @{ML_response_fake [display,gray]
  1339   "Conv.no_conv @{cterm True}" 
  1342   "Conv.no_conv @{cterm True}" 
  1340   "*** Exception- CTERM (\"no conversion\", []) raised"}
  1343   "*** Exception- CTERM (\"no conversion\", []) raised"}
  1341 
  1344 
  1342   A further basic conversion is, for example, @{ML "Thm.beta_conversion"}:
  1345   A more interesting conversion is the function @{ML "Thm.beta_conversion"}: it 
       
  1346   produces an equation between a term and its beta-normal form. For example
  1343 
  1347 
  1344   @{ML_response_fake [display,gray]
  1348   @{ML_response_fake [display,gray]
  1345   "Thm.beta_conversion true @{cterm \"(\<lambda>x. x \<or> False) True\"}"
  1349   "let
  1346   "(\<lambda>x. x \<or> False) True \<equiv> True \<or> False"}
  1350   val add = @{cterm \"\<lambda>x y. x + (y::nat)\"}
  1347 
  1351   val two = @{cterm \"2::nat\"}
  1348   User-defined rewrite rules can be applied by the conversion
  1352   val ten = @{cterm \"10::nat\"}
  1349   @{ML "Conv.rewr_conv"}. Consider, for example, the following rule:
  1353 in
       
  1354   Thm.beta_conversion true (Thm.capply (Thm.capply add two) ten)
       
  1355 end"
       
  1356   "((\<lambda>x y. x + y) 2) 10 \<equiv> 2 + 10"}
       
  1357 
       
  1358   Note that the actual response in the example is @{term "2 + 10 \<equiv> 2 + (10::nat)"}, 
       
  1359   since the pretty-printer of @{ML_type cterm}s already beta-normalises terms.
       
  1360   However, we can by how we constructed the term (using the function 
       
  1361   @{ML Thm.capply}, which is the application @{ML $} for @{ML_type cterm})
       
  1362   that the left-hand side must contain beta-redexes.
       
  1363 
       
  1364   The argument @{ML true} in @{ML Thm.beta_conversion} indicates that 
       
  1365   the right-hand side should be fully beta-normalised. If @{ML false} is
       
  1366   given, then only a beta-reduction is performed on the outer-most level.
       
  1367   For example
       
  1368 
       
  1369   @{ML_response_fake [display,gray]
       
  1370   "let
       
  1371   val add = @{cterm \"\<lambda>x y. x + (y::nat)\"}
       
  1372   val two = @{cterm \"2::nat\"}
       
  1373 in
       
  1374   Thm.beta_conversion false (Thm.capply add two)
       
  1375 end"
       
  1376   "((\<lambda>x y. x + y) 2) \<equiv> \<lambda>y. 2 + y"} 
       
  1377 
       
  1378   Again, we actually see as output only the fully normalised term 
       
  1379   @{term "\<lambda>y. 2 + y"}.
       
  1380 
       
  1381   The main point of conversions is that they can be used for rewriting terms.
       
  1382   For this you can use the function @{ML "Conv.rewr_conv"}. Suppose we want 
       
  1383   to rewrite a term according to the (meta)equation:
       
  1384 
  1350 *}
  1385 *}
  1351 
  1386 
  1352 lemma true_conj1: "True \<and> P \<equiv> P" by simp
  1387 lemma true_conj1: "True \<and> P \<equiv> P" by simp
  1353 
  1388 
  1354 text {*
  1389 text {* 
  1355   Here is how this rule can be used for rewriting:
  1390   then we can use it in order to rewrite @{term "True \<and> (Foo \<longrightarrow> Bar)"}:
  1356 
  1391 
  1357   @{ML_response_fake [display,gray]
  1392   @{ML_response_fake [display,gray]
  1358   "Conv.rewr_conv @{thm true_conj1} @{cterm \"True \<or> False\"}"
  1393 "let 
  1359   "True \<and> False \<equiv> False"}
  1394   val ctrm =  @{cterm \"True \<and> (Foo \<longrightarrow> Bar)\"}
  1360 *}
  1395 in
  1361 
  1396   Conv.rewr_conv @{thm true_conj1} ctrm
  1362 text {*
  1397 end"
  1363   Basic conversions can be combined with a number of conversionals, i.e.
  1398   "True \<and> (Foo \<longrightarrow> Bar) \<equiv> Foo \<longrightarrow> Bar"}
  1364   conversion combinators:
  1399 
       
  1400   The function @{ML Conv.rewr_conv} only does rewriting on the outer-most
       
  1401   level, otherwise it raises the exception @{ML CTERM}.
       
  1402 
       
  1403   This very primitive way of rewriting can be made more powerful by
       
  1404   combining several conversions into one. For this you can use conversion
       
  1405   combinators. The simplest conversion combinator is @{ML then_conv}, 
       
  1406   which applies one conversion after another. For example
  1365 
  1407 
  1366   @{ML_response_fake [display,gray]
  1408   @{ML_response_fake [display,gray]
  1367   "(Thm.beta_conversion true then_conv Conv.rewr_conv @{thm true_conj1})
  1409 "let
  1368   @{cterm \"(\<lambda>x. x \<and> False) True\"}"
  1410   val conv1 = Thm.beta_conversion true
       
  1411   val conv2 = Conv.rewr_conv @{thm true_conj1}
       
  1412   val ctrm = Thm.capply (@{cterm \"\<lambda>x. x \<and> False\"}) (@{cterm \"True\"})
       
  1413 in
       
  1414   (conv1 then_conv conv2) ctrm
       
  1415 end"
  1369   "(\<lambda>x. x \<and> False) True \<equiv> False"}
  1416   "(\<lambda>x. x \<and> False) True \<equiv> False"}
  1370 
  1417 
       
  1418   The conversion combinator @{ML else_conv} tries out the 
       
  1419   first one, and if it does not apply, tries the second. For example 
       
  1420 
  1371   @{ML_response_fake [display,gray]
  1421   @{ML_response_fake [display,gray]
  1372   "(Conv.rewr_conv @{thm true_conj1} else_conv Conv.all_conv)
  1422 "let
  1373   @{cterm \"P \<or> (True \<and> Q)\"}"
  1423   val conv = Conv.rewr_conv @{thm true_conj1} 
  1374   "P \<or> (True \<and> Q) \<equiv> P \<or> (True \<and> Q)"}
  1424              else_conv Conv.all_conv
       
  1425   val ctrm1 = @{cterm \"True \<and> Q\"}
       
  1426   val ctrm2 = @{cterm \"P \<or> (True \<and> Q)\"}
       
  1427 in
       
  1428   (conv ctrm1, conv ctrm2)
       
  1429 end"
       
  1430 "(True \<and> Q \<equiv> Q, 
       
  1431  P \<or> True \<and> Q \<equiv> P \<or> True \<and> Q)"}
       
  1432 
       
  1433   Here the conversion of @{thm [source] true_conj1} only applies
       
  1434   in the first case, but fails in the second. The whole conversion
       
  1435   does not fail because the combinator @{ML else_conv} will then 
       
  1436   try out @{ML Conv.all_conv}, which allways succeeds.
       
  1437 
       
  1438   The combinator @{ML Conv.arg_conv} will apply the conversion on
       
  1439   the first argument, taht is the term must be of the form 
       
  1440   @{ML "t1 $ t2" for t1 t2} and the conversion is applied to @{text t2}.
       
  1441   For example
  1375 
  1442 
  1376   @{ML_response_fake [display,gray]
  1443   @{ML_response_fake [display,gray]
  1377   "Conv.arg_conv (Conv.rewr_conv @{thm true_conj1})
  1444 "let 
  1378   @{cterm \"P \<or> (True \<and> Q)\"}"
  1445   val conv = Conv.rewr_conv @{thm true_conj1}
  1379   "P \<or> (True \<and> Q) \<equiv> P \<or> Q"}
  1446   val ctrm = @{cterm \"P \<or> (True \<and> Q)\"}
  1380 
  1447 in
  1381   \begin{readmore}
  1448   Conv.arg_conv conv ctrm
  1382   See @{ML_file "Pure/conv.ML"} for more conversionals. Further basic conversions
  1449 end"
  1383   can be found in, for example, @{ML_file "Pure/thm.ML"},
  1450 "P \<or> (True \<and> Q) \<equiv> P \<or> Q"}
  1384   @{ML_file "Pure/drule.ML"}, and @{ML_file "Pure/meta_simplifier.ML"}.
  1451 
  1385   \end{readmore}
  1452   The reason for this behaviour is that @{text "(op \<or>)"} expects two arguments
  1386 
  1453   and so is of the form @{text "Const \<dots> $ t1 $ t2"}. The conversion is then 
  1387   We will demonstrate this feature in the following example.
  1454   applied to @{text "t2"} which stands for @{term "True \<and> Q"}.
  1388 
  1455 
  1389   To begin with, let's assumes we want to simplify with the rewrite rule
  1456 *}
       
  1457 
       
  1458 
       
  1459 text {*
       
  1460   To begin with, let us assumes we want to simplify with the rewrite rule
  1390   @{text true_conj1}. As a conversion, this may look as follows:
  1461   @{text true_conj1}. As a conversion, this may look as follows:
  1391 *}
  1462 *}
       
  1463 
  1392 
  1464 
  1393 ML{*fun all_true1_conv ctxt ct =
  1465 ML{*fun all_true1_conv ctxt ct =
  1394   (case Thm.term_of ct of
  1466   (case Thm.term_of ct of
  1395     @{term "op \<and>"} $ @{term True} $ _ => 
  1467     @{term "op \<and>"} $ @{term True} $ _ => 
  1396       (Conv.arg_conv (all_true1_conv ctxt) then_conv
  1468       (Conv.arg_conv (all_true1_conv ctxt) then_conv
  1406   @{ML_response_fake [display,gray]
  1478   @{ML_response_fake [display,gray]
  1407   "all_true1_conv @{context}
  1479   "all_true1_conv @{context}
  1408   @{cterm \"distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x\"}"
  1480   @{cterm \"distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x\"}"
  1409   "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x \<equiv> distinct [1, x] \<longrightarrow> 1 \<noteq> x"}
  1481   "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x \<equiv> distinct [1, x] \<longrightarrow> 1 \<noteq> x"}
  1410 
  1482 
  1411   Now, let make the task a bit more  complicated by rewrite according to the rule
  1483   Now, let us make the task a bit more complicated by rewriting according to the rule
  1412   @{text true_conj1}, but only in the first arguments of @{term If}:
  1484   @{text true_conj1}, but only in the first arguments of @{term If}:
  1413 *}
  1485 *}
  1414 
  1486 
  1415 ML{*fun if_true1_conv ctxt ct =
  1487 ML{*fun if_true1_conv ctxt ct =
  1416   (case Thm.term_of ct of
  1488   (case Thm.term_of ct of
  1474   conversion @{ML all_true1_conv} again:
  1546   conversion @{ML all_true1_conv} again:
  1475 
  1547 
  1476   @{ML_response_fake [display,gray]
  1548   @{ML_response_fake [display,gray]
  1477   "Conv.fconv_rule (all_true1_conv @{context}) @{lemma \"P \<or> (True \<and> \<not>P)\" by simp}" 
  1549   "Conv.fconv_rule (all_true1_conv @{context}) @{lemma \"P \<or> (True \<and> \<not>P)\" by simp}" 
  1478   "P \<or> \<not>P"}
  1550   "P \<or> \<not>P"}
       
  1551 
       
  1552   \begin{readmore}
       
  1553   See @{ML_file "Pure/conv.ML"} for more information about conversion combinators. 
       
  1554   Further conversions are defined in  @{ML_file "Pure/thm.ML"},
       
  1555   @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}.
       
  1556   \end{readmore}
  1479 *}
  1557 *}
  1480 
  1558 
  1481 
  1559 
  1482 
  1560 
  1483 section {* Structured Proofs *}
  1561 section {* Structured Proofs *}