src/HOL/AxClasses/Tutorial/Group.thy
author wenzelm
Wed, 02 Aug 2000 19:40:14 +0200
changeset 9502 50ec59aff389
parent 9363 86b48eafc70d
child 10007 64bf7da1994a
permissions -rw-r--r--
adapted deriv;

(*  Title:      HOL/AxClasses/Tutorial/Group.thy
    ID:         $Id$
    Author:     Markus Wenzel, TU Muenchen
*)

theory Group = Main:;

subsection {* Monoids and Groups *};

consts
  times :: "'a => 'a => 'a"    (infixl "[*]" 70)
  inverse :: "'a => 'a"
  one :: 'a;


axclass
  monoid < "term"
  assoc:      "(x [*] y) [*] z = x [*] (y [*] z)"
  left_unit:  "one [*] x = x"
  right_unit: "x [*] one = x";


axclass
  semigroup < "term"
  assoc: "(x [*] y) [*] z = x [*] (y [*] z)";

axclass
  group < semigroup
  left_unit:    "one [*] x = x"
  left_inverse: "inverse x [*] x = one";

axclass
  agroup < group
  commute: "x [*] y = y [*] x";


subsection {* Abstract reasoning *};

theorem group_right_inverse: "x [*] inverse x = (one::'a::group)";
proof -;
  have "x [*] inverse x = one [*] (x [*] inverse x)";
    by (simp only: group.left_unit);
  also; have "... = one [*] x [*] inverse x";
    by (simp only: semigroup.assoc);
  also; have "... = inverse (inverse x) [*] inverse x [*] x [*] inverse x";
    by (simp only: group.left_inverse);
  also; have "... = inverse (inverse x) [*] (inverse x [*] x) [*] inverse x";
    by (simp only: semigroup.assoc);
  also; have "... = inverse (inverse x) [*] one [*] inverse x";
    by (simp only: group.left_inverse);
  also; have "... = inverse (inverse x) [*] (one [*] inverse x)";
    by (simp only: semigroup.assoc);
  also; have "... = inverse (inverse x) [*] inverse x";
    by (simp only: group.left_unit);
  also; have "... = one";
    by (simp only: group.left_inverse);
  finally; show ?thesis; .;
qed;

theorem group_right_unit: "x [*] one = (x::'a::group)";
proof -;
  have "x [*] one = x [*] (inverse x [*] x)";
    by (simp only: group.left_inverse);
  also; have "... = x [*] inverse x [*] x";
    by (simp only: semigroup.assoc);
  also; have "... = one [*] x";
    by (simp only: group_right_inverse);
  also; have "... = x";
    by (simp only: group.left_unit);
  finally; show ?thesis; .;
qed;


subsection {* Abstract instantiation *};

instance monoid < semigroup;
proof intro_classes;
  fix x y z :: "'a::monoid";
  show "x [*] y [*] z = x [*] (y [*] z)";
    by (rule monoid.assoc);
qed;

instance group < monoid;
proof intro_classes;
  fix x y z :: "'a::group";
  show "x [*] y [*] z = x [*] (y [*] z)";
    by (rule semigroup.assoc);
  show "one [*] x = x";
    by (rule group.left_unit);
  show "x [*] one = x";
    by (rule group_right_unit);
qed;


subsection {* Concrete instantiation *};

defs (overloaded)
  times_bool_def:   "x [*] y == x ~= (y::bool)"
  inverse_bool_def: "inverse x == x::bool"
  unit_bool_def:    "one == False";

instance bool :: agroup;
proof (intro_classes,
    unfold times_bool_def inverse_bool_def unit_bool_def);
  fix x y z;
  show "((x ~= y) ~= z) = (x ~= (y ~= z))"; by blast;
  show "(False ~= x) = x"; by blast;
  show "(x ~= x) = False"; by blast;
  show "(x ~= y) = (y ~= x)"; by blast;
qed;


subsection {* Lifting and Functors *};

defs (overloaded)
  times_prod_def: "p [*] q == (fst p [*] fst q, snd p [*] snd q)";

instance * :: (semigroup, semigroup) semigroup;
proof (intro_classes, unfold times_prod_def);
  fix p q r :: "'a::semigroup * 'b::semigroup";
  show
    "(fst (fst p [*] fst q, snd p [*] snd q) [*] fst r,
      snd (fst p [*] fst q, snd p [*] snd q) [*] snd r) =
       (fst p [*] fst (fst q [*] fst r, snd q [*] snd r),
        snd p [*] snd (fst q [*] fst r, snd q [*] snd r))";
    by (simp add: semigroup.assoc);
qed;

end;