Given two typeclasses (e.g. group and monoid), I have seen both the subclass and the instance commands used to establish the fact that any group is also a monoid (i.e. the subclass relation), as shown in the example below.

The two commands seem to generate similar proof requirements, but also have some differences so that the proof for one does not work for the other sometimes. For example (Isabelle 2021):

theory test
  imports Main HOL.Set

declare [[show_types]] [[show_sorts]]

instance group βŠ† monoid
  fix x::"'a::group"
  have "Γ· x βŠ• (x βŠ• 𝟬) = Γ·x βŠ• x" by (simp add: invl neutl assoc_left)
  from this show "x βŠ• 𝟬 = x" by (simp add: left_cancel)

subclass (in group) monoid
  fix x::"'a::group"  (* problem line*)


The instance command generates the following proof goal:

proof (state)
goal (1 subgoal):
 1. β‹€x::'a. x βŠ• 𝟬 = x
type variables:
  'a :: group

, while the subclass command generates a similar goal but without the type constraint 'a::group:

proof (state)
goal (1 subgoal):
 1. β‹€x::'a. x βŠ• 𝟬 = x
  neutral :: 'a
  plus :: 'a β‡’ 'a β‡’ 'a
type variables:
  'a :: type

So the first command fix x::"'a::group" that worked in the instance case no longer works for the subclass case.

To me, the proof goal of the instance command seems more natural, as one starts from a group and just need to prove that it also respects the laws of monoid.

My questions are:

Are the two usages with instance/subclass supposed to be equivalent or do they express some fundamentally different facts/ideas?

If yes, when is one preferred over the other? If no, how are they different in terms of intended usage.

(I asked the same question in SO a couple of months ago, but have not received any response. Posting here to hopefully get more attention.)


1 Answer 1


Citing The Isabelle/Isar Reference which is part of the official documentation:

A weakened form of [subclass] is available through a further variant of instance: instance c1 βŠ† c2 opens a proof that class c2 implies c1 without reference to the underlying locales; this is useful if the properties to prove the logical connection are not sufficient on the locale level but on the theory level.

We can see this with the same example as yours in Tutorial.Axioms, on line 149 we have a theory level lemma:

theorem left_cancel:
 ((?x::?'a::group) βŠ• (?y::?'a::group) = ?x βŠ• (?z::?'a::group)) = (?y = ?z)

And on line 166 (instance group βŠ† monoid) can fix x :: 'a group as you noticed, but we also get access to left_cancel on line 172.

For subclass (in group) monoid we only get x :: 'a :: type and no access to theory level theorems (eg. left_cancel). It is still provable and will register a sublocale group < monoid which instance won't.

Now, to answer your two questions:

  1. These usages of instance and subclass are not supposed to be equivalent. For example, as you have noticed yourself, the former carries the theory level sort 'a :: group.

  2. If you the locale level is not sufficient to prove the connection, you can go with the former. The latter is useful if you want to access theorems from c2 inside the c1 context.

More references: Haskell-style type classes with Isabelle/Isar and Tutorial to Locales and Locale Interpretation


Your Answer

By clicking β€œPost Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.