I am trying to understand how "inheritance" work at locale/interpretation level. I have an abstract locale (locA), with a method (g) defined within it. I have a concrete locale (locB), which is an instance/model of the abstract one. Is there a way to use the g method in such a way that I don't get a "type unification" error?
Below is a toy example of what I am trying to achieve
theory InstOverwrite
imports Main
begin
locale locA =
fixes f :: "'a ⇒ 'b"
begin
definition g :: "'a set ⇒ 'b set" where
"g X = f`X"
end
locale locB =
fixes fb :: "nat ⇒ nat"
assumes fb_def: "fb n = n*2"
begin
interpretation locA
apply unfold_locales
done
end
context locB
begin
definition fx :: "nat set ⇒ nat set" where
"fx X = {n+1 | n::nat. n ∈ locA.g X}"
end
end
Unsurprisingly, I get the following error:
Type unification failed: Clash of types "_ set" and "_ ⇒ _"
Type error in application: incompatible operand type
Operator: locA.g :: (??'a ⇒ ??'b) ⇒ ??'a set ⇒ ??'b set
Operand: X :: nat set
Quick fix
Within your code, you have not actually connected the two locales.
locA.gexists “outside” the locale context in the sense that it must be supplied anf :: "'a ⇒ 'b"in order to be used. This is what Isabelle tries to express by stressingOperator: locA.g :: (??'a ⇒ ??'b) ⇒ ??'a set ⇒ ??'b set. So, in order to make the type checker happy here, you would need to explicitly say thatfbshould serve asfin the function application.(The only difference is writing
locA.g fb Xinstead oflocA.g X.)Providing parameters to
interpretationFrom your description of the problem, I gather that you hoped
interpretation locAwould have taken care of establishing this connection. This is not the case.To establish the instantiation that
f := fb, you would need to supply parameters to the interpretation. The following would work:(Note that it's now
g Xinstead oflocA.g fb X!)Maybe rather
sublocale?I conveniently dropped the end/begin context from the example script. The reason being that the context jumps would kill the interpretation. If you want the connection to persist across contexts, the
sublocalekeyword is more appropriate:Further notes on locale inheritance
Depending on what you're actually wanting to do, an even more different formulation might make sense. I assume that the listing is just the way it is to have some minimal example.
For people bumping into this question, I want to note that the locale inheritance situation here might be expressed more conveniently by one of the two following approaches:
A) Make
locBextendlocA:The following will use the same
ffor both locales directly and just add the defining assumption:B) Make
locBinstantiate parameters forlocA