This question is related to my previous SO question about type classes. I ask this question to set up a future question about locales. I don\'t think type classes will work for
I partially answer my question, and part of the reason is to refer to this when I ask a question about Isar subtypes. By all appearances, my question and answer here is related to subtypes.
As to whether I can fix the problem with type classes that I described, I don't know about that.
(UPDATE: The likely solution for my use of type classes will be a combination of ideas, part of the solution being type coercion, as explained in the answer to my SO question: What is an Isabelle/HOL subtype? What Isar commands produce subtypes?
If using the locales in Groups.thy is the way to go for me, then the corresponding type classes to those locales will probably also work. I can instantiate a class such as semigroup_add
, use lift_definition
to define the plus
operator, and even lift my operators that return a bool
into the type. The operators that can't be lifted into the new type are somewhat nonsensical in the context of the new type anyway, wherein type coercion can come into play to make sense of them for things like unions of sets. The devil is in the details.)
With what I said I want out of types and subtypes, I figured out I do get a form of that with typedef
, the form being the functions Rep
and Abs
, which I have been working with a little.
As described in isar-ref.pdf pg. 242,
For typedef t = A the newly introduced type t is accompanied by a pair of morphisms to relate it to the representing set over the old type. By default, the injection from type to set is called Rep t and its inverse Abs t...
Below, I use Rep
and Abs
in a small example to demonstrate that I can relate my main type, sT
, with the new type I define with typedef
, which is type tsA
.
I don't think type classes are of ultimate importance. There are two main things I'm exploring,
For example, in Groups.thy, there is
locale semigroup =
fixes f :: "'a => 'a => 'a" (infixl "*" 70)
assumes assoc [ac_simps]: "a * b * c = a * (b * c)"
If I don't use subtypes, I think I'll have to do something like this, where inP
is my \<in>
(I'm just starting with locales):
locale sgA =
fixes G :: sT
fixes f :: "sT => sT => sT" (infixl "*" 70)
assumes closed:
"(a inP G) & (b inP G) --> (a * b) inP G"
assumes assoc:
"(a inP G) & (b inP G) & (c inP G) --> (a * b) * c = a * (b * c)"
Part of the answer in being able to use Groups.semigroup
could be the use of Rep
and Abs
; I use the operator of type tsA => tsA => tsA
on type tsA
, but when the elements of type tsA
need to be treated as elements of type sT
, then I use Rep
on them to map them to type sT
.
I haven't thought all this out or experimented enough to know what will work best, but I gave this partial answer to try and explain more of what I have in my mind. There might be someone else out there with some good information to add.
The subtypes approach may not be all upside, as shown below by the last two theorem
commands in the example code. The left-hand side of the implications are necessary because I'm not exploiting the power of types, similar to closed
and assoc
above in locale sgA
. However, in spite of that, it's no problem for my simp
rules, whereas, the theorems that are using Rep
and Abs
are requiring metis
for the proofs, and it might require a lot of ugly overhead to get things working smoother.
Below I include the file A_iSemigroup_xp.thy. This is an ASCII version of iSemigroup_xp.thy. These require the import of MFZ.thy, where these 3 files are in this GitHub folder.
theory A_iSemigroup_xp
imports MFZ
begin
--"[END]"
--"EXAMPLE (Possible subtype for a trivial semigroup)"
typedef tsA = "{x::sT. x = emS}"
by(simp)
theorem "(Rep_tsA x) inP {.Rep_tsA x.}"
by(metis
SSi_exists)
theorem "! x::tsA. x = (Abs_tsA emS)"
by(metis (lifting, full_types)
Abs_tsA_cases
mem_Collect_eq)
theorem "! x. x inP {.emS.} --> x = emS"
by(simp)
theorem "! x. x inP {.z inP {.emS.} ¦ z = emS.} --> x = emS"
by(simp)
--"[END]"
--"ISAR (Theory end)"
end