The Isabelle library contains the classes real_inner and real_normed_vector, the latter of which is declared a subclass of the former in ~~src/HOL/Library/Inner_Product.thy.
Now, suppose we have a locale
locale foo =
fixes goo :: "'a::{real_normed_vector} => bool"
and wish to extend this locale with some new constants, and also constraining the sort of 'a to be real_inner at the same time, like so:
locale extended = foo +
fixes ext :: "'a::{real_inner} => nat"
Is there a way to do this? Trying to do this using the examples above sees Isabelle give goo the type 'b::{real_normed_vector} => bool in extended, when I instead require the type 'a::{real_inner} => bool.
You can do it like this:
locale extended = foo goo
for goo :: "'a :: real_inner ⇒ bool" +
fixes ext :: "'a => nat"
Related
I started using Isabelle/Simpl and write the following theory according to the user guide:
theory Scratch
imports Simpl.Simpl
begin
hoarestate newvars =
N :: nat
lemma (in newvars) "Γ ⊢ {} ´N :== ´N + 1 {}"
sorry
end
But Isabelle complains that type unification fails:
Type unification failed
Type error in application: operator not of function type
Operator: N_' :: 'a
Operand: s :: ??'a
Simpl itself (including its user guide) successfully compiles.
How can I make it pass?
As Javier Díaz pointed out, importing only Simpl.Vcg instead of Simpl.Simpl does the trick.
The cause of the error seems a name collision against a record defined in Simpl.SyntaxTest. It contains the following record definition:
record 'g vars = "'g state" +
A_' :: "nat list"
AA_' :: "nat list list"
I_' :: nat
M_' :: nat
N_' :: nat
R_' :: int
S_' :: int
B_' :: bool
Abr_':: string
p_' :: ref
q_' :: ref
Isabelle seems to prefer N_' in the record to N in the hoarestate, although the hoarestate is defined later😥. I don't know why this is the case.
I'm trying to define a generic operations for a programming language:
type_synonym vname = "string"
type_synonym 'a env = "vname ⇒ 'a option"
locale language =
fixes big_step :: "'exp × 'val env ⇒ 'val ⇒ bool" (infix "⇒" 55)
fixes typing :: "'type env ⇒ 'exp ⇒ 'type ⇒ bool" ("(1_/ ⊢/ (_ :/ _))" [50,0,50] 50)
For example this is a particular language:
datatype foo_exp =
FooBConst bool |
FooLet vname foo_exp foo_exp |
FooVar vname |
FooAnd foo_exp foo_exp
datatype foo_val = FooBValue bool | FooIValue int
type_synonym foo_env = "foo_val env"
datatype foo_type = FooBType | FooIType
type_synonym foo_tenv = "foo_type env"
inductive foo_big_step :: "foo_exp × foo_env ⇒ foo_val ⇒ bool"
inductive foo_typing :: "foo_tenv ⇒ foo_exp ⇒ foo_type ⇒ bool"
How to make it an instance of language locale?
Is it possible to use same notation (⇒ and _ ⊢ _ : _) for different languages in one theory? Could this notation be polymorphic?
To specialize the parameters of a locale, you need to do an interpretation as in
interpretation foo: language foo_big_step foo_typing .
This will generate an abbreviation foo.f for every definition f in the locale language specialised to foo_big_step and foo_typing and every theorem thm of language becomes specialised to foo.thm. The mixfix syntax annotations of parameters and all constants in the locale will not be inherited.
Type classes cannot be used in this context because your locale depends on multiple type variables and type classes in Isabelle support only exactly one type variable.
If you want to use some kind of polymorphic notation for the big-step semantics and type judgements, Adhoc_Overloading might work, provided that Isabelle's parser can statically resolve the overloading uniquely. Here's how this might work:
theory Language imports Main "~~/src/Tools/Adhoc_Overloading" begin
type_synonym 'a env = "vname ⇒ 'a option"
consts
big_step :: "'exp × 'val env ⇒ 'val ⇒ bool" (infix "⇒" 55)
typing :: "'type env ⇒ 'exp ⇒ 'type ⇒ bool" ("(1_/ ⊢/ (_ :/ _))" [50,0,50] 50)
locale language =
fixes big_step :: "'exp × 'val env ⇒ 'val ⇒ bool"
fixes typing :: "'type env ⇒ 'exp ⇒ 'type ⇒ bool"
begin
adhoc_overloading Language.big_step big_step
adhoc_overloading Language.typing typing
end
After the interpretation, you have to register foo's semantics and type judgement constants foo_big_step and foo_typing for adhoc overloading with the syntactic constants big_step and typing again.
interpretation foo: language foo_big_step foo_typing .
adhoc_overloading Language.big_step foo_big_step
adhoc_overloading Language.typing foo_typing
So when you write
term "(x :: foo_exp, E) ⇒ v"
thereafter, Isabelle's parser will figure out by the types that this refers to foo_big_step, and inside the locale Language, term "(x :: 'exp, E) ⇒ v" is resolved to the locale parameter big_step.
This should also work for multiple interpretations of the locale Language provided that the types are sufficient to uniquely resolve the overloading. If not, you'll get error messages, which are not always easy to understand.
Two classes are defined containing the same function, but when the two classes is used in a locale there is an unification error:
theory Scratch
imports Main
begin
class c1 =
fixes getName :: "'a ⇒ string"
class c2 =
fixes getName :: "'a ⇒ string"
locale c12 =
fixes match :: "('a::c1) ⇒ ('b::c2) ⇒ bool"
assumes as : "match a b ⟶ (getName a) = (getName b)"
end
The unification error is resolved by renaming (getName b) to (getName_b b) and use the class definition
class c2 =
fixes getName_b :: "'a ⇒ string"
Does a solution exist without renaming?
Here a solution is given when the overloading is needed when datatypes are parameters.
Fully or partially qualified identifiers can be used. I used find_consts, as shown below, to find the qualified names of the type class constants.
The type inference only required that I use c1_class.getName a to get rid of the error.
theory Scratch
imports Complex_Main
begin
class c1 =
fixes getName :: "'a => string"
class c2 =
fixes getName :: "'a => string"
find_consts name: getName (*
find_consts
name: "getName"
found 2 constant(s):
Scratch.c1_class.getName :: "'a => char list"
Scratch.c2_class.getName :: "'a => char list"
*)
declare[[show_sorts]]
locale c12 =
fixes match :: "('a::c1) => ('b::c2) => bool"
assumes as : "match a b --> (c1_class.getName a) = (getName b)"
end
I am working with limits and I am unable to prove the following
definition func :: "real ⇒ real"
where "func = real"
lemma "(λh. (func (x+h))) -- 0 --> (func (x))"
unfolding func_def
apply (auto intro!: tendsto_eq_intros)
However if I replace the definition of func to
definition func :: "real ⇒ real"
where "func x = x"
the lemma is solved.
How can I solve this lemma when working with generic definitions?
I believe, here the problem is that the function real has just a generic (overloaded) syntax, i.e., real :: 'a => real, but it is not necessarily defined for all possible types 'a. This is easily seen when using find_theorems: when searching for lemmas on real :: nat => real, you get plenty of results whereas searching for real :: real => real doesn't give you a single result.
find_theorems "real :: real => real"
find_theorems "real :: nat => real"
Consequently, you can not even prove a simple lemma like func x = x, since it is not specified that real :: real => real really is the identity function.
When entering the following definition
datatype env = "nat => 'a option"
Isabelle/jedit shows an exclamation mark and says
Legacy feature! Bad name binding: "nat => 'a option"
What is the problem and how can I fix this type synonym?
Update: even
datatype 'a env = "nat => 'a option"
which is better a definition in theory did not solve the problem.
On the right-hand side of a datatype definition, you normally list the constructors of the datatype. In your example, you have not written any constructor, so datatype thinks that you want to call it nat => 'a option, which is not a legal name for a constructor or any other Isabelle constant.
If you just want to introduce env as a type abbreviation for nat => 'a option, type_synonym is what you are looking for.
type_synonym 'a env = "nat => 'a option"
Note that you have to repeat all type variables on the left-hand side. Then, 'a env and nat => 'a option can be used interchangeably. If you want to introduce a new type constructor for env, then you must provide a constructor name such as Env:
datatype 'a env = Env "nat => 'a option"