1

Some of my locals have quite a few assumptions, very much resembling inductions over data types (that’s where the assumptions come from). When interpreting such a locale, having named cases would be very handy. How do I achieve that the following works?

locale Foo = 
  fixes P
  assumes 0: "P 0"
  assumes Suc: "P n ⟹ P (Suc n)"

interpretation Foo "λ _ . True"
proof(default)
  case 0 show ?case..
next
  case (Suc n) show ?case ..
qed
chris
  • 4,988
  • 20
  • 36
Joachim Breitner
  • 25,395
  • 6
  • 78
  • 139

2 Answers2

2

The method default internally calls the methods rule, unfold_locales and intro_classes. None of these support case names (for unfold_locales, this has been discussed already on the Isabelle mailing list in 2008). So there is no way to get the case_name system to work with default. That thread mentions two important points:

  1. If your locale hierarchy is flat, unfold_locales essentially just applies the rule Foo.intro where Foo is the name of the locale. If you have a complex hierarchy of locales, it checks which interpretations are already available and combines the .intro rules accordingly.

  2. cases is the canonical method to get case names.

Thus, you can get case names manually with the case_name attribute:

interpretation Foo "λ _ . True"
proof(cases rule: Foo.intro[case_names 0 Suc])

Of course, you can also tag a theorem with the case names if you need it multiple times:

lemmas Foo_intro[case_names 0 Suc] = Foo.intro

The problem with case name support in unfold_locales is that the implementation does not keep track of which subgoal comes from which locale inheritance. If you have some spare time, feel free to implement support for case names.

Andreas Lochbihler
  • 4,998
  • 12
  • 10
  • Thanks, especially for pointing out `Foo.intro`. I had the feeling that this was the case, but cound’t find it, because the theorem does not show up when I issue `find_theorems Foo`. – Joachim Breitner Oct 16 '14 at 13:53
  • I had the same trouble and thus used the awkward auxiliary lemmas in my answer below. – chris Oct 16 '14 at 19:33
1

As far as I know methods induct and case are responsible for setting up named cases. Thus I don't see a way that default would do as you ask.

You could introduce a new rule like

lemma foo_rule [case_names 0 Suc]:
  assumes "P 0"
    and "⋀n. P n ⟹ P (Suc n)"
  shows "foo P"
  using assms by (simp add: foo_def)

or alternatively like

lemmas foo_rule [case_names 0 Suc] =
  conjI [THEN foo_def [THEN meta_eq_to_obj_eq, THEN iffD2], rule_format]

if you are thusly inclined. And then use

interpretation foo "λ_. True"
proof (induct rule: foo_rule)

Accidentally I found out that declaring foo_rule [case_names 0 Suc, induct type] allows you to omit the rule name, i.e.,

interpretation foo "λ_. True"
proof (induct)

But I could imagine that this would break existing default induct rules.

chris
  • 4,988
  • 20
  • 36