Isabelle/ZF infix definition issue - isabelle

I tried to define a definition like this:
theory intext
imports ZF.Int
begin
definition zmod :: "[i,i] ⇒ i" (infixl "$//" 69)
where
"a $// b == 0"
However, it shows error in "$//" the "a $// b == 0":
Inner syntax error⌂
Failed to parse prop
I tried to see if there is infix definition in ZF.Int, and I do find it, but the Isabelle shows error in the theory at the beginning:
Cannot update finished theory "ZF.Int"
May I know does anyone has experience in defining definition with infix operator in Isabelle/ZF could give me some advice?

The character / is a special character in mixfix annotations, therefore you need to escape it using ' as follows:
definition zmod :: "[i,i] ⇒ i" (infixl "$'/'/" 69)
where
"a $// b == 0"
For more information regarding mixfix annotations please refer to The Isabelle/Isar Reference Manual, section 8.2.
Regarding the error message Cannot update finished theory "ZF.Int", this means that Int is part of ZF and cannot be edited.

Related

Isabelle/HOL: access interpretation in another locale

There's an Isabelle/HOL library that I want to build on with new definitions and proofs. The library defines locale2, which I'd like to build upon. Inside locale2, there's an interpretation of locale1.
To extend locale2 in a separate theory, I define locale3 = locale2. Inside locale3, however, I can't figure out how to access locale2's interpretation of locale1. How can I do that? (Am I even going about this in the right way at all?)
Below is an MWE. This is the library theory with the locale I want to extend:
theory ExistingLibrary
imports Main
begin
(* this is the locale with the function I want *)
locale locale1 = assumes True
begin
fun inc :: "nat ⇒ nat"
where "inc n = n + 1"
end
(* this is the locale that interprets the locale I want *)
locale locale2 = assumes True
begin
interpretation I: locale1
by unfold_locales auto
end
end
This is my extension theory. My attempt is at the bottom, causing an error:
theory MyExtension
imports ExistingLibrary
begin
locale locale3 = locale2
begin
definition x :: nat
where "x = I.inc 7" (* Undefined constant: "I.inc" *)
end
end
Interpretations inside a context last only until the end of the context. When the context is entered again, you have to repeat the interpretation to make the definitions and theorems available:
locale 3 = locale2 begin
interpretation I: locale1 <proof>
For this reason, I recommend to split the first interpretation step into two:
A lemma with a name that proves the goal of the interpretation step.
The interpretation command itself which can be proved by(rulelemma)
If you want the interpretation to take place whenever you open the locale and whenever you interpret the locale, then sublocale instead of interpretation might be better.

quotient_type warning "no map function"

When using the quotient_type command I get the following warning: "No map function defined for Example.A. This will cause problems later on".
Here is a minimal example to trigger the warning(tested with Isabelle2017).
theory Example
imports
Main
begin
datatype 'a A = B "'a A" | C
(*for map: map *) (* uncommenting doesn't fix the warning*)
quotient_type 'a Q = "'a A" / "op ="
by (rule identity_equivp)
end
So my questions are:
What is meant by a map function in this context (I only do know the concept of a map function in the context of functors in functional programming)?
What does it have to do with the datatype packages map functions, like one that would be generated by the commented line?
Which problems will one get later on?
The datatype command does not by default register the generated map function with the quotient package because there may be more general mappers (in case there are dead type variables). You therefore must do the functor declaration manually:
functor map_A
by(simp_all add: A.map_id0 A.map_comp o_def)
The mapper and its theorems are needed if you later want to lift definitions through the quotient type. This has been discussed on the Isabelle mailing list.

Using syntax/translations wiith locales

Is there any known hack that allows custom syntax for definitions inside a given locale, using the syntax/translation mechanism? All of my attempts at an "obvious" solution are generating type errors, which I am led to believe is caused by syntax/translation not yet being made "locale-aware".
Raw AST transformations with syntax and translations cannot be used inside locales in Isabelle2016. There is a workaround for constants and types whose declaration does not depend on locale parameters. You merely have to issue the syntax declaration outside of the locale for the appropriate constant from background theory. Below is a proof of concept:
locale test = fixes a :: nat begin
definition foo :: "nat ⇒ nat" where "foo x = x"
end
syntax "_foo" :: "nat ⇒ bool" ("FOO")
translations "FOO" ↽ "CONST test.foo"
context test begin
term foo
This workaround does not work for constants which depend on parameters of the locale, because then constant in the background theory takes these parameters as additional arguments and the locale installs an abbreviation, which is folded before the custom syntax translation fires.

hiding operators to avoid ambiguities in the AST

I'm trying the list example from the official Isabelle tutorial. I replaced the # with : and the # with ++ to have the same syntax as Haskell. Now I get warnings about ambiguities in the AST. I know that I can hide functions with hide_const but this doesn't work for operators in infix notation. How can I hide operators in Isabelle?
The exact warning message is:
Ambiguous input⌂ produces 2 parse trees:
("\<^const>HOL.Trueprop"
("\<^const>HOL.eq" ("\<^const>Map.map_add" ("/<^const>toylist.list.Nil") ("_position" ys))
("_position" ys)))
("\<^const>HOL.Trueprop"
("\<^const>HOL.eq" ("\<^fixed>app" ("\<^const>toylist.list.Nil") ("_position" ys)) ("_position" ys)))
Fortunately, only one parse tree is well-formed and type-correct,
but you may still want to disambiguate your grammar or your input.
Hiding an operator does not delete its notation. There is a separate command no_notation to delete existing notations. In Isabelle/HOL, ++ is bound to map_add as can be seen from the ambiguity warning. You can delete it as follows.
no_notation map_add (infixl "++" 100)
Note that you must repeat the exact precedence parameters with which the notation to be deleted has been declared. There is no easy way to find the notation declaration for a constant, but it is good style to declare notation close to the declaration of the constant; Ctrl-clicking on a constant takes you to its declaration.
Regarding :, this is by default bound to Set.member. You can delete it with no_notation Set.member ("(_/ : _)" [51, 51] 50).
Unless for demonstatory or exploratory purposes, I recommend not to change the default syntax of Isabelle too much. Otherwise, other Isabelle users will find it hard to read your code and your theories will not be compatible with others'. The reason is that when importing different theories, notations are merged additively. Thus, if you delete the notation ++ for map_add in theory A and theory B imports the theories A and some other theory derived from Main but not A, then the ambiguity for ++ is back in theory B.
You can use the command no_notation which takes the same arguments that were used during the notation declaration with the command notation (or within the constant definition).
Both symbols : and ++ are already used by Set.member and map_add respectively. So you have to find these notation declarations and use them in no_notation:
no_notation Set.member ("(_/ : _)" [51, 51] 50)
no_notation map_add (infixl "++" 100)
Then you can proceed in the same way you certainly already have, and by removing the now obsolete syntax for list:
no_notation Cons (infixr "#" 65)
notation Cons (infixr ":" 65)
no_notation List.append (infixr "#" 65)
notation List.append (infixr "++" 65)
term "x : (xs ++ ys)"
The notation for Set.member : would not really miss as there already is the xsymbol/utf-8 notation ∈. I think map_add is not that used, but you could then use the free notation # for it.

Can I overload the notation for operators that are assigned to bool and list?

(NOTE: If I can get rid of the warning I show below, then I say a bunch of extraneous stuff. As part of asking a question, I also do some opinionating. I guess that's sort of asking the question "Why am I wrong here in what I say?")
It seems that 6 of the symbols used for bool operators should have been assigned to syntactic type classes, and bool instantiated for those type classes. In particular, these:
~, &, |, \<not>, \<and>, \<or>.
Because type annotation of terms is a frequent requirement for HOL operators, I don't think it would be a great burden to have to use bool annotations for those 6 operators.
I would like to overload those 6 symbols for other logical operators. Not having the usual symbols for an application can result in there being no good solution for notation.
In the following example source, if I can get rid of the warnings, then the problem is solved (unless I would be setting a trap for myself):
definition natOP :: "nat => nat => nat" where
"natOP x y = x"
definition natlistOP :: "nat list => nat list => nat list" where
"natlistOP x y = x"
notation
natOP (infixr "&" 35)
notation
natlistOP (infixr "&" 35)
term "True & False"
term "2 & (2::nat)"
term "[2] & [(2::nat)]" (*
OUTPUT: Ambiguous input produces 3 parse trees:
...
Fortunately, only one parse tree is well-formed and type-correct,
but you may still want to disambiguate your grammar or your input.*)
Can I get rid of the warnings? It seems that since there's a type correct term, there shouldn't be a problem.
There are actually other symbols I also want, such as !, used for list:
term "[1,2,3] ! 1"
Here's the application for which I want the symbols:
Verilog HDL Operators.
Update
Based on Brian Huffman's answer, I unnotate &, and switch & to a syntactic type class. It'll work out, or it won't, indeed, binary logic, so diversely applicable. My general rule is "don't mess with default Isabelle/HOL".
(*|Unnotate; switch to a type class; see someday why this is a bad idea.|*)
no_notation conj (infixr "&" 35)
class conj =
fixes syntactic_type_classes_are_awesome :: "'a => 'a => 'a" (infixr "&" 35)
instantiation bool :: conj
begin
definition syntactic_type_classes_are_awesome_bool :: "bool => bool => bool"
where "p & q == conj p q"
instance ..
end
term "True & False"
value "True & False"
declare[[show_sorts]]
term "p & q" (* "(p::'a::conj) & (q::'a::conj)" :: "'a::conj" *)
You can "undeclare" special syntax using the no_notation command, e.g.
no_notation conj (infixr "\<and>" 35)
This infix operator is then available to be used with your own functions:
notation myconj (infixr "\<and>" 35)
From here on, \<and> refers to the constant myconj instead of the HOL library's standard conjunction operator for type bool. You should have no warnings about ambiguous syntax. The original HOL boolean operator is still accessible by name (conj), or you can give it a different syntax if you want with another notation command.
For the no_notation command to work, the pattern and fixities must be exactly the same as they were declared originally. See src/HOL/HOL.thy for the declarations of the operators you are interested in.
I should warn about a potential pitfall: Subsequent theory merges can bring the original syntax back into scope, causing ambiguous syntax again. For example, say your theory A.thy imports Main and redeclares the \<and> syntax. Then your theory B.thy imports both A and another library theory, say Complex_Main. Then in theory B, \<and> will be ambiguous. To prevent this, make sure to put all your external theory imports in the one theory file where you change the syntax; then have all of your other theories import this one.

Resources