Hi again,
I've been getting great help here, so here's another problem I've ran into.
I have been working towards proving a behavior that executes an HTTP request, so proving the serialization and deserialization of the data has been a main component of that. What I'm running into now is that a theorem that I've proven for nat
is not being used to simplify a record that contains a nat
value. Here's what I mean:
type_synonym http_data = string
record order =
amount :: nat
fun deserialize :: "http_data ⇒ order" where
"deserialize d = ⦇ amount = (nat_of_string d) ⦈"
fun serialize :: "order ⇒ http_data" where
"serialize ord = string_of_nat (amount ord)"
(* This theorem has been successfully proven *)
theorem ser_deser: "nat_of_string (string_of_nat n) = n"
I would then expect to be able to prove this as follows:
lemma "deserialize (serialize order) = order"
apply(cases order)
apply(simp add: ser_deser)
This leaves me with the following goal:
1. ⋀amount.
order = ⦇amount = amount⦈ ⟹
nat_of_string (map char_of (digit_list amount)) = amount
The map char_of ...
is part of the definition of string_of_nat
, but I was hoping that the simplifier would see nat_of_string (string_of_nat amount)
and simplify that to amount
, especially since I specified ser_deser
as a simplification rule.
Is there something obvious to do here to discharge the goal, or are there some gotchas with using records?
The problem is that string_of_nat is automatically unfolded to "map char_of" by the simplifier before using ser_deser. Not unfolding string_of_nat with "simp del: string_of_nat.simps" should do the trick.
That is exactly the issue - ok. I'm definitely understanding a bit more what gets automatically applied and what should be added / removed explicitly. Thanks so much!
Alex Weisberger has marked this topic as resolved.
All the rules in the simp set get used for rewriting by the simplifier (i.e. simp
, auto
, force
, fastforce
) automatically. The fun
and primrec
commands add all the definitional rules that they create to the simpset by default. Other definitional commands (like definition
, inductive
) do not. This is because that is usually the kind of behaviour that you want: If you do a non-recursive definition, you are introducing that definition as a reason (to hide complexity). If you define a recursive function, you usually want the simplifier to break down things automatically.
That's a great point about a non-recursive function hiding complexity. I went and changed both string_of_nat
and serialize
to definitions. Then I was able to prove via:
theorem "deserialize (serialize order) = order"
apply(cases order)
apply(simp add: serialize_def)
done
Last updated: Dec 21 2024 at 16:20 UTC