Define a type variable as either one of two options - isabelle

In Isabelle/HOL, we would like to define multi-variable polynomials over either the naturals or the integers. Is there a way to write
datatype ('a::???) polynomial = ...
and specify that 'a should be either nat or int? A syntax like 'a::nat|int would seem intuitive at first, but unfortunately doesn't work.
A possible alternative would be to specify 'a::comm_semiring (possibly also adding countable) but we don't really need the full generality of abstract commutative semirings.

Related

"Efficient" least- and greatest fixpoint computations?

I am trying to compute two finite sets of some enumerable type (let's say char) using a least- and greatest- fixpoint computation, respectively. I want my definitions to be extractable to SML, and to be "semi-efficient" when executed. What are my options?
From exploring the HOL library and playing around with code generation, I have the following observations:
I could use the complete_lattice.lfp and complete_lattice.gfp constants with a pair of additional monotone functions to compute my sets, which in fact I currently am doing. Code generation does work with these constants, but the code produced is horribly inefficient, and if I understand the generated SML code correctly is performing an exhaustive search over every possible set in the powerset of characters. Any use, no matter how simple, of these two constants at type char therefore causes a divergence when executed.
I could try to make use of the iterative fixpoint described by the Kleene fixpoint theorem in directed complete partial orders. From exploring, there's a ccpo_class.fixp constant in the theory Complete_Partial_Order, but the underlying iterates constant that this is defined in terms of has no associated code equations, and so code cannot be extracted.
Are there any existing fixpoint combinators hiding somewhere, suitable for use with finite sets, that produce semi-efficient code with code generation that I have missed?
None of the general fixpoint combinators in Isabelle's standard library is meant to used directly for code extraction because their construction is too general to be usable in practice. (There is another one in the theory ~~/src/HOL/Library/Bourbaki_Witt_Fixpoint.) But the theory ~~/src/HOL/Library/While_Combinator connects the lfp and gfp fixpoints to the iterative implementation you are looking for, see theorems lfp_while_lattice and gfp_while_lattice. These characterisations have the precondition that the function is monotone, so they cannot be used as code equations directly. So you have two options:
Use the while combinator instead of lfp/gfp in your code equations and/or definitions.
Tell the code preprocessor to use lfp_while_lattice as a [code_unfold] equation. This works if you also add all the rules that the preprocessor needs to prove the assumptions of these equations for the instances at which it should apply. Hence, I recommend that you also add as [code_unfold] the monotonicity statement of your function and the theorem to prove the finiteness of char set, i.e., finite_class.finite.

How to use a vector as a type parameter in Julia

This is similar to my previous question, but a bit more complicated.
Before I was defining a type with an associated integer as a parameter, Intp{p}. Now I would like to define a type using a vector as a parameter.
The following is the closest I can write to what I want:
type Extp{g::Vector{T}}
c::Vector{T}
end
In other words, Extp should be defined with respect to a Vector, g, and I want the contents, c, to be another Vector, whose entries should be the of the same type as the entries of g.
Well, this does not work.
Problem 1: I don't think I can use :: in the type parameter.
Problem 2: I could work around that by making the types of g and c arbitary and just making sure the types in the vectors match up in the constructor. But, even if I completely take everything out and use
type Extp{g}
c
end
it still doesn't seem to like this. When I try to use it the way I want to,
julia> Extp{[1,1,1]}([0,0,1])
ERROR: type: apply_type: in Extp, expected Type{T<:Top}, got Array{Int64,1}
So, does Julia just not like particular Vectors being associated with types? Does what I'm trying to do only work with integers, like in my Intp question?
EDIT: In the documentation I see that type parameters "can be any type at all (or an integer, actually, although here it’s clearly used as a type)." Does that mean that what I'm asking is impossible, and that that only types and integers work for Type parameters? If so, why? (what makes integers special over other types in Julia in this way?)
In Julia 0.4, you can use any "bitstype" as a parameter of a type. However, a vector is not a bitstype, so this is not going to work. The closest analog is to use a tuple: for example, (3.2, 1.5) is a perfectly valid type parameter.
In a sense vectors (or any mutable object) are antithetical to types, which cannot change at runtime.
Here is the relevant quote:
Both abstract and concrete types can be parameterized by other types
and by certain other values (currently integers, symbols, bools, and
tuples thereof).
So, your EDIT is correct. Widening this has come up on the Julia issues page (e.g., #5102 and #6081 were two related issues I found with some discussion), so this may change in the future - I'm guessing not in v0.4 though. It'd have to be an immutable type really to make any sense, so not Vector. I'm not sure I understand your application, but would a Tuple work?

How do I create a synonym for a type class name?

I want to abbreviate create a synonym for a type class name. Here's how I'm doing it now:
class fooC = linordered_idom
instance int :: fooC
proof qed
definition foof :: "'a::fooC ⇒ 'a" where
"foof x = x"
term "foof (x::int)"
value "foof (x::int)"
This works fine if there's not a better way to do it. The disadvantage is that I have to instantiate int, and the class command takes time to implement itself.
Update 140314
This update is to clarify for Makarius what it is I want, to explain my purpose in wanting it, and give a list of commands that I'm familiar with for creating notation, abbreviations, and synonyms, but commands which I couldn't get to work for what I want.
My initial choice of "abbreviation" rather than "synonym"
I guess "synonym" would have been a better word, but I chose "abbreviation" because it describes what I want, which is to be able to create a shorter name for for a type class, like renaming linordered_semidom to losdC. Though Isar abbreviation has some of the attributes of definition, it also just defines syntax. So, because "abbreviate" describes what I want, and abbreviation just defines syntax, I chose "abbreviation" instead of "synonym" or "alias".
Synonym/alias, Isar commands I couldn't get to work for that
"Alias" would describe what I want. As to the sentence "If you just want to save typing in the editor, you could use some abbreviations there," here are the commands I've experimented with to try and rename linordered_idom, but I couldn't get them to work for me:
type_notation
type_synonym
notation
abbreviation
syntax
Rather than explain what I've tried, and try to remember what I tried, I just list them. I did searches on "class" and only found the Isar commands class and classes. I thought maybe locale commands might be applicable, but I didn't find anything.
What I want is simple, like how type_synonym is used to define synonyms for types.
The purpose
There is my general desire to shorten type class names such as linordered_idom, because eventually, I plan on using the algebra type classes extensively.
However, there is a second reason, and that is to rename something like linordered_semidom to be part of a naming scheme of three types.
For any algebraic type class, such as linordered_semidom, I can use that type class, along with quotient_type, to create what I'll call a number system, such as how nat is used to define int.
Using Int.thy as a template, I did that with linordered_semidom, and then instantiated it as comm_ring_1, which is as far as I have time to go these days.
Additionally, with typedef, for any algebraic type class which has the dependencies of zero and one (and others such as ord), I can define a type of all elements greater than or equal to zero, and another one for all elements greater than zero. I did that for linordered_idom, but then I figured out that I actually needed to go the quotient_type route, to get things that model rat.
That's the long explanation. Eventually, I'll start working with numerous algebraic type classes, and from one type class, I'll get two more. If I do that for 20 type classes, and also use them, then long, descriptive names don't work, and renaming type classes will help me in knowing what type classes go together.
Here would be the scheme for linordered_semidom, where I don't know how this will actually work out, until I'm able to try it all:
linordered_semidom is the base class. I rename it to losdC. It's the numbers greater than or equal to zero for these three types.
losdQ is defined from losdC using quotient_type. It gives me the negative numbers, and the ability to coerce losdC to losdQ.
losd1 is defined using typedef, and is the numbers greater than zero.
I need a consistent naming scheme, to keep it all straight: losdC, losdQ, and losd1.
Finally, eventually even 4 types instead of 3 types
I haven't completely worked and thought things out (I'm not even close), but analogously, it's all related to implementing, for algebra type classes, the basic relationship between nat, int, and rat, where real might eventually come into play. Additionally, it's about getting a type, from these types, of the non-negative or positive members, if those don't come by default.
There is nat used for int, and int used for rat.
With nat used for int, we get the non-negative integers by default, which is nat.
With int used for rat, we don't get the non-negative members of rat, we get fractions. (Again, I'm talking about a type of non-negatives and positives, not a set of non-negatives and positives.)
So, if I use linordered_idom and quotient_type to define fractions, then I have to use typedef twice to get the non-negative and positive members of those fractions, which means I would have 4 types to keep track of, liodC, liodQ, liod0, and liod1.
If there's a simple solution to renaming type classes, then I've unnecessarily said about 600 words.
A definition is not an abbreviation, it introduces a separate term that is logical equal. That works for term constants.
A type class is semantically a predicate over types, and thus connected to some predicate (term constant), but in practice you rarely access that.
So what exactly means to "abbreviate a type class"?
For example, you might want to manipulate the class name space to get an alias for it, which is in principle possible. But what is the purpose?
If you just want to save typing in the editor, you could use some abbreviations there.
Another possibility, within the formal system, is to introduce genuine aliases in the name space. Isabelle provides some facilities for that, which are not very much advertized, because there is a real danger of obscuring libraries and preventing anyone else from understanding them, if names are changed too much.
This is how it works, using some friendly Isabelle/ML within the theory source:
class foobar = ord + fixes foobar :: 'a
setup {* Sign.class_alias #{binding f} #{class foobar} *}
typ "'a::f"
instantiation nat :: f
begin
definition foobar_nat :: nat where "foobar_nat = 0"
instance ..
end
Note that Sign.class_alias only refers to the type class name space in the narrow sense. A class is many things at the same time: locale, const (the prodicate), type class. You can see this in the following examples where the class is used as "target" for local definitions and theorems:
definition (in foobar) "fuzz = foobar"
theorem (in foobar) "fuzz = foobar" by (simp add: fuzz_def)
Technically, the locale name space used above could support aliases as well, but this is not done. Only basic Sign.class_alias, Sign.type_alias, Sign.const_alias are exposed for unusual situations, to address problems with legacy libraries.

Can I define multiple names for a theorem?

Suppose I have a theorem:
theorem non_ASCII_thm_name:
"True"
by simp
I want to define an ASCII name for non_ASCII_thm_name with something like the notation command. For example, like this:
notation non_ASCII_thm_name ("ASCII_thm_name")
The Isar commands notation and abbreviation can only be used with constants. Is there an Isar command that allows me to to this?
Preferably, all I want my Isar command to provide is a synonym. For example, if I use sledgehammer, it would be preferable that there exist only one theorem, non_ASCII_thm_name, so that sledgehammer is not using an additional fact ASCII_thm_name.
A partial solution is to use the command:
lemmas ASCII_thm_name = non_ASCII_thm_name
This will define a new theorem called ASCII_thm_name which will be the same as non_ASCII_thm_name.
There is unfortunately no guarantee that tools such as find_theorems will use your new name, but will instead use their own heuristics for determining which is the "best" name to output back to the user.
An alternative synonym for lemmas is theorems, though the former is considered to be the more standard approach.

What's the concise notation for "option values"?

Is there a mathematical symbol or otherwise concise notation to represent option values (OCaml's option type, Haskell's Maybe...)?
It appears so often in functional programming that I would expect to find a concise syntax for this type, the same way lists have a somewhat standard [] notation, functions have the -> notation, and so on.
I know that in a more formal context one might use a partial function notation , but in most cases it doesn't fit as nicely as some explicit symbols for Some/None (or Just/Nothing).
Ideally, I'd like to write something like:
This function returns #42 if the input is valid, # otherwise.
Where #42 represents Some 42 and # represents None, but in a standard way, easily understandable by most readers (or at least those with some mathematical background).
I haven't seen any such specific notation. The closest I know is to use of mathematical symbols to express the type: α ⊕ 1. Here ⊕ represents direct sum (disjoint union) of types and 1 represents the unit type.
This notation is used in category theory or in typing systems.

Resources