Function definition with one argument as index - isabelle

This question is somewhat related to function with index
Imagine the definition of the function is
definition myf :: "nat => nat => nat" where
"myf n a = n * a"
and I want to use a more readable abbreviation
"f<sub>n</sub> a"
instead of
"myf n a"
I have tried
definition myf :: "nat => nat => nat" **("f<sub>_</sub> _" [90])** where
"f<sub>n</sub> a = n * a"
and I get the error
Head of definition "fn" differs from declaration "myf".
How am I supposed to write the prefix s.t. it gives me what I am looking for?
Thank you in advance

Subscripts that span a region of text can be marked up with \<^bsub>...\<^esub> (or, equivalently, ⇘...⇙). Therefore, your definition should be as follows:
definition myf :: "nat => nat => nat" ("f⇘_⇙") where
"f⇘n⇙ a = n * a"
For further information see Appendix B in The Isabelle/Isar Reference Manual.

Related

"String of nat" in Isabelle?

I'm struggling to find a function of type nat => string that converts terms like
42
into terms like
''42''
Does it exist? I've found char_of_nat (in the String library) but that's a bit too low-level, being concerned with ASCII codes and the like.
In the archive of formal proofs, under Real_Impl/Show you find a class show with a function essentially of type 'a => string. In Real_Impl/Show_Instances several common types are instantiated, including nat, rat, and int.
In the meantime, I've gone ahead and written my own string_of_nat and string_of_int functions. In the absence of other pre-existing functions, these will suit me fine.
fun string_of_nat :: "nat ⇒ string"
where
"string_of_nat n = (if n < 10 then [char_of_nat (48 + n)] else
string_of_nat (n div 10) # [char_of_nat (48 + (n mod 10))])"
definition string_of_int :: "int ⇒ string"
where
"string_of_int i = (if i < 0 then ''-'' # string_of_nat (nat (- i)) else
string_of_nat (nat i))"
There's a Haskell-like show class in the AFP entry Show.
The instance for the nat type is in Show.Show_Instances.
Example:
theory Show_Test
imports "Show.Show_Instances"
begin
lemma "show (123 :: nat) = ''123''"
by (simp add: Show_Instances.shows_prec_nat_def showsp_nat.simps shows_string_def)
end

Unfold/simp has no effect in a primrec type class instantiation proof

Up until several days ago, I always defined a type, and then proved theorems directly about the type. Now I'm trying to use type classes.
Problem
The problem is that I can't instantiate cNAT for my type myD below, and it appears it's because simp has no effect on the abstract function cNAT, which I've made concrete with my primrec function cNAT_myD. I can only guess what's happening because of the automation that happens after instance proof.
Questions
Q1: Below, at the statement instantiation myD :: (type) cNAT, can you tell me how to finish the proof, and why I can prove the following theorem, but not the type class proof, which requires injective?
theorem dNAT_1_to_1: "(dNAT n = dNAT m) ==> n = m"
assumes injective: "(cNAT n = cNAT m) ==> n = m"
Q2: This is not as important, but at the bottom is this statement:
instantiation myD :: (type) cNAT2
It involves another way I was trying to instantiate cNAT. Can you tell me why I get Failed to refine any pending goal at shows? I put some comments in the source to explain some of what I did to set it up. I used this slightly modified formula for the requirement injective:
assumes injective: "!!n m. (cNAT2 n = cNAT2 m) --> n = m"
Specifics
My contrived datatype is this, which may be useful to me someday: (Update: Well, for another example maybe. A good mental exercise is for me to try and figure out how I can actually get something inside a 'a myD list, other than []. With BNF, something like datatype_new 'a myD = myS "'a myD fset" gives me the warning that there's an unused type variable on the right-hand side)
datatype 'a myD = myL "'a myD list"
The type class is this, which requires an injective function from nat to 'a:
class cNAT =
fixes cNAT :: "nat => 'a"
assumes injective: "(cNAT n = cNAT m) ==> n = m"
dNAT: this non-type class version of cNAT works
fun get_myL :: "'a myD => 'a myD list" where
"get_myL (myL L) = L"
primrec dNAT :: "nat => 'a myD" where
"dNAT 0 = myL []"
|"dNAT (Suc n) = myL (myL [] # get_myL(dNAT n))"
fun myD2nat :: "'a myD => nat" where
"myD2nat (myL []) = 0"
|"myD2nat (myL (x # xs)) = Suc(myD2nat (myL xs))"
theorem left_inverse_1 [simp]:
"myD2nat(dNAT n) = n"
apply(induct n, auto)
by(metis get_myL.cases get_myL.simps)
theorem dNAT_1_to_1:
"(dNAT n = dNAT m) ==> n = m"
apply(induct n)
apply(simp) (*
The simp method expanded dNAT.*)
apply(metis left_inverse_1 myD2nat.simps(1))
by (metis left_inverse_1)
cNAT: type class version that I can't instantiate
instantiation myD :: (type) cNAT
begin
primrec cNAT_myD :: "nat => 'a myD" where
"cNAT_myD 0 = myL []"
|"cNAT_myD (Suc n) = myL (myL [] # get_myL(cNAT_myD n))"
instance
proof
fix n m :: nat
show "cNAT n = cNAT m ==> n = m"
apply(induct n)
apply(simp) (*
The simp method won't expand cNAT to cNAT_myD's definition.*)
by(metis injective)+ (*
Metis proved it without unfolding cNAT_myD. It's useless. Goals always remain,
and the type variables in the output panel are all weird.*)
oops
end
cNAT2: Failed to refine any pending goal at show
(*I define a variation of `injective` in which the `assumes` definition, the
goal, and the `show` statement are exactly the same, and that strange `fails
to refine any pending goal shows up.*)
class cNAT2 =
fixes cNAT2 :: "nat => 'a"
assumes injective: "!!n m. (cNAT2 n = cNAT2 m) --> n = m"
instantiation myD :: (type) cNAT2
begin
primrec cNAT2_myD :: "nat => 'a myD" where
"cNAT2_myD 0 = myL []"
|"cNAT2_myD (Suc n) = myL (myL [] # get_myL(cNAT2_myD n))"
instance
proof (*
goal: !!n m. cNAT2 n = cNAT2 m --> n = m.*)
show
"!!n m. cNAT2 n = cNAT2 m --> n = m"
(*Failed to refine any pending goal
Local statement fails to refine any pending goal
Failed attempt to solve goal by exported rule:
cNAT2 (n::nat) = cNAT2 (m::nat) --> n = m *)
Your function cNAT is polymorphic in its result type, but the type variable does not appear among the parameters. This often causes type inference to compute a type which is more general than you want. In your case for cNAT, Isabelle infers for the two occurrences of cNAT in the show statement the type nat => 'b for some 'b of sort cNAT, but their type in the goal is nat => 'a myD. You can see this in jEdit by Ctrl-hovering over the cNAT occurrences to inspect the types. In ProofGeneral, you can enable printing of types with using [[show_consts]].
Therefore, you have to explicitly constrain types in the show statement as follows:
fix n m
assume "(cNAT n :: 'a myD) = cNAT m"
then show "n = m"
Note that it is usually not a good idea to use Isabelle's meta-connectives !! and ==> inside a show statement, you better rephrase them using fix/assume/show.

Isabelle: Evaluating formula with Quantifiers

Why does the following work:
fun f :: "nat ⇒ bool" where
"f _ = (True ∨ (∀x. x))"
But this fails
fun g :: "nat ⇒ bool" where
"g _ = (True ∨ (∀a. True))"
with
Additional type variable(s) in specification of "g_graph": 'a
Specification depends on extra type variables: "'a"
The error(s) above occurred in "test.g_sumC_def"
The error(s) above occurred in definition "g_sumC_def":
"g_sumC ≡ λx. THE_default undefined (g_graph TYPE('a) x)"
Similarly, the following succeeds,
value "True ∨ (∀x. x)"
but this fails
value "True ∨ (∀x. True)"
with
Wellsortedness error:
Type 'a not of sort enum
Cannot derive subsort relation {} < enum
The short answer is: In your first function definition type inference easily infers that x is of type bool, while in your second definition, the bound variable a is not used anywhere else and thus its type is arbitrary ('a). Which is what Additional type variable(s) in specification ... expresses.
If you constrain the type of a explicitly, e.g.,
fun g :: "nat ⇒ bool" where
"g _ = (True ∨ (∀a::bool. True))"
the function definition is accepted.
A longer answer: Since the definition of g is not recursive you could turn it into using definition instead of fun. Then your first attempt does not fail completely but the result might surprise you. After
definition g :: "nat ⇒ bool" where
"g _ = (True ∨ (∀a. True))"
the type of g is 'a itself => nat => bool instead of the intended nat => bool. The reason is the same as for the failure of fun before. Since a is of arbitrary type, this additional type has to be recorded in the type of g, which is done by introducing an additional dummy argument which just states this additional type explicitly. Here 'a itself is a type whose constructor TYPE(...) -- taking a type as argument -- allows us to encode type information on the term level. E.g.,
TYPE('a) :: 'a itself
TYPE(bool) :: bool itself
TYPE(nat) :: nat itself
Then g TYPE(nat) is the version of g where a is fixed to be of type nat.
Concerning your value statements, the reason for the second one to fail is not really related to the above. In the first statement the universal quantifier binds a variable of type bool whose values can be enumerated explicitly and thus a result can be computed by considering all those values. In contrast, in your second statement the bound variable x is of an arbitrary type 'a whose values cannot be enumerated explicitly.
The following fails:
fun f where "f _ = (∀a. True)"
because the type of a has hidden polymorphism (i.e., there is a type variable inside your function's body that is not present in the function's type signature), which upsets the function package's internal proofs.
If you explicitly give a a type as so:
fun f where "f _ = (∀a::bool. True)"
or is you give a a type that is also in the function's type signature, as so:
fun f where "f _ = (∀a::bool. True)"
the function definition succeeds. Your example:
fun f where "f _ = (∀x. x)"
succeeds, because x is forced to be type bool.
As for your value commands, Isabelle attempts to generate executable code for your expression, and hence needs to not only know the type of your for-all statements, but also be able to enumerate all possible values of it, so that it can test them all. Types such as bool work fine, but type variables like 'a or infinite types such as nat are not enumerable, and hence Isabelle cannot generate code for them.

How can I remove all elements in a list with a certain property?

I want to match and remove those elements in l :: 'a list that match the predicate P :: ('a => bool)
What is the best way to accomplish such a task? How can I find out about existing functions that might help me?
One way to find functions you expect to exist is the document What's in Main from the Isabelle documentation. It gives a quick overview of the main types, functions and syntax provided by the theory Main of Isabelle/HOL.
If you look at the List section in ths document, you find the function filter which seems to have the correct type.
Short Story: Use find_consts
Long Story:
This a How-To to conquer such problems.
In Main, there is List.dropWhile
List.dropWhile :: "('a => bool) => 'a list => 'a list"
However, it only removes from the beginning. This may not be the intended function.
value "List.dropWhile (λ x. x = ''c'') [''c'', ''c'', ''d'']"
"[''d'']"
value "List.dropWhile (λ x. x = ''c'') [''d'', ''c'', ''c'']"
"[''d'', ''c'', ''c'']"
Manual Approach
We can write a function ourselves which removes all occurrences
fun dropAll :: "('a => bool) => 'a list => 'a list" where
"dropAll P [] = []"
| "dropAll P (x # xs) = (if P x then dropAll P xs else x # (dropAll P xs))"
Searching the Library
However, this function is equivalent to filtering with ¬ P
How can we find such library functions?
If we know the signature of what we want to do, we can use find_consts
find_consts "('a ⇒ bool) ⇒ 'a list ⇒ 'a list"
It returns 3 functions from Main, with that signature: List.dropWhile, List.filter, List.takeWhile
Now, let's show that we don't need dropAll but can do the same with filter.
lemma "dropAll P l = filter (λ x. ¬ P x) l"
apply(induction l)
by simp_all
It is advisable not to implement things like dropAllyourself but rather use filter. Thus, all lemmata proven for filter are usable.
Hints
Hint: we can use the convenient list comprehension syntax to write e.g. filter expressions
lemma "filter (λ x. ¬ P x) l = [x ← l. ¬ P x]" by simp

Using tuples in definitions

I want to create a definition which has a tuple as its argument.
definition my_def :: "('a × 'a) ⇒ bool" where
"my_def (a, b) ⟷ a = b"
However, this is not accepted. The error message is
Bad arguments on lhs: "(a, b)"
The error(s) above occurred in definition:
"my_def (a, b) ≡ a = b"
Using fun instead of definition works but this is not what I want. The following notation also works but is somewhat ugly:
definition my_def :: "('a × 'a) ⇒ bool" where
"my_def t ⟷ fst t = snd t"
What is the best way to use tuples as arguments in a definition?
Using fun is probably the least painful way to do this, the definition package doesn't recognise patterns on the left hand side.
Another option is to use tuple patterns for lambda expressions:
my_def ≡ %(a,b). a = b

Resources