I know how to make "term abbreviations" in Isabelle, but can I make "type abbreviations" that behave in the same way?
I can define a "term abbreviation" using
abbreviation "foo == True"
Henceforth all appearances of True in the output will be printed as foo. For instance, the command
term "True ⟶ False"
outputs "foo ⟶ False". I would like to define a "type abbreviation" that has this same behaviour. I know about the type_synonym command, but when I type
type_synonym baz = "int list"
then appearances of int list in future output are not replaced with baz as I would like them to be. If it doesn't already exist in some form, I think a type_abbreviation command could be quite handy when the right-hand side of the definition is rather unwieldy.
You can declare syntax translations for types just as it had to be done for terms before abbreviation was introduced. For example, the following makes Isabelle pretty-print char list as string. More examples of this kind can be found in the Isabelle distribution in MicroJava.
translations
(type) "string" <= (type) "char list"
The command translations works for type abbreviations where each type variable occurs exactly once on each side. If you have multiple occurrences of a type variable on the right hand side, you have to write a parse translation in ML. Examples of this can be found in JinjaThreads in the AFP (search for print_translation).
Related
Specific example: Let's say I have demonstrated that I have a graph in the sense of https://www.isa-afp.org/theories/category3/#FreeCategory.html :
lemma i_have_a_graph: shows "graph Obj Arr Dom Cod"
sorry
where the symbols Obj, Arr, Dom, and Cod were defined earlier in the file. This gives me access to the lemmas and theorems stated within the graph locale.
How do I use the symbol path defined within the graph locale?
Related question with no answers: Access definitions from sublocale
You don't do it using a lemma but by the interpretation command:
interpretation MyGraph: graph Obj Are Dom Cod <proof>
Of course, the <proof> could use your lemma, but you don't need to prove such a lemma separately.
Now MyGraph.path refers to the path component of this instance.
See https://www.cl.cam.ac.uk/research/hvg/Isabelle/dist/Isabelle/doc/locales.pdf
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.
Please I learned Isabelle recently and I have problem in type declaration for "fun" or "definition" for example:
definition mos :: "real => real => real set"
where "mos u ≡ {(∀t∈T. ∃!x. vector(t,x)∈u)}"
please I couldn't understand how to define types for statements as I have many arguments.
I couldn't find clear description of how to declare types in the manuals, so if there is any helpful manual or reference that will be great.
Another thing, I tried to use command "typ" to check the varable type but it didn't work!.
In Julia, is there a way to write a macro that branches based on the (compile-time) type of its arguments, at least for arguments whose types can be inferred at compile time? Like, in the example below, I made up a function named code_type that returns the compile-time type of x. Is there any function like that, or any way to produce this kind of behavior? (Or do macros get expanded before types are inferred, such that this kind of thing is impossible.)
macro report_int(x)
code_type(x) == Int64 ? "it's an int" : "not an int"
end
Macros cannot do this, but generated functions can.
Check out the docs here: https://docs.julialang.org/en/v1/manual/metaprogramming/#Generated-functions-1
In addition to spencerlyon2's answer, another option is to just generate explicit branches:
macro report_int(x)
:(isa(x,Int64) ? "it's an int" : "not an int")
end
If #report_int(x) is used inside a function, and the type of x can be inferred, then the JIT will be able to optimise away the dead branch (this approach is used by the #evalpoly macro in the standard library).
(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.