I am trying to define valid quadruple ⊨ {P}c×c'{Q} of Hoare logic in Isabelle/HOL, where c and c' are commands and P and Q are assertions. Assertions are defined as :
type_synonym assn = "state × state ⇒ bool"
I have defined the valid quadruple as following:
definition
rel_hoare_valid :: "assn ⇒ com × com ⇒ assn ⇒ bool" ("⊨ {(1_)}/ (_)/ {(1_)}" 50)
where "⊨ {P}c×c'{Q} = ..."
... contains rest of the code, which is not relevant.
I know that the syntax annotation part
("⊨ {(1_)}/ (_)/ {(1_)}" 50)
is not correct, but I don't know how to fix it.
The error message is as following:
Type unification failed: Clash of types "_ set" and "_ × _"
Type error in application: incompatible operand type
Operator: rel_hoare_valid P :: com × com ⇒ ((char list ⇒ int) × (char
list ⇒ int) ⇒ bool) ⇒ bool
Operand: c × c' :: (??'a × ??'b) set
Related
I am trying to define some vertex labels in Isabelle HOL and have a problem with the successor definition:
record ('v,'w) graph =
nodes :: "('v×'w) set"
edges :: "(('v×'w) × ('v×'w)) set"
definition succ :: "('v,'w) graph ⇒'v ⇒ ('v,'w) set"
where "succ G v ≡ {(v',w). ((v,w),(v',w))∈edges G}"
It says "Bad number of arguments for type constructor: "Set.set"", does anyone know how to fix this?
succ shall probably return a set of vertex-label pairs 'v × 'w, so want to write
definition succ :: "('v,'w) graph ⇒'v ⇒ ('v × 'w) set"
I am defining subclass and subtype relations as inductive predicates for a Java-like language and would like to generate code for these relations. Defining and generating code for the subtype relation was no problem:
type_synonym class_name = string
record class_def =
cname :: class_name
super :: "class_name option"
interfaces :: "class_name list"
type_synonym program = "class_def list"
(* Look up a class by its name *)
definition lookup_class :: "program ⇒ class_name ⇒ class_def option" where
"lookup_class P C ≡ find (λcl. (class_def.cname cl) = C) P"
(* Direct subclass relation *)
inductive is_subclass1 :: "program ⇒ class_name ⇒ class_name ⇒ bool" where
"⟦
Some cl = lookup_class P C;
(class_def.super cl) = Some C'
⟧ ⟹ is_subclass1 P C C'"
(* Reflexive transitive closure of `is_subclass1` *)
definition is_subclass :: "program ⇒ class_name ⇒ class_name ⇒ bool" where
"is_subclass P C C' ≡ (is_subclass1 P)⇧*⇧* C C'"
code_pred(modes: i ⇒ i ⇒ i ⇒ bool, i ⇒ i ⇒ o ⇒ bool) is_subclass1 .
code_pred
(modes: i ⇒ i ⇒ i ⇒ bool, i ⇒ i ⇒ o ⇒ bool)
[inductify]
is_subclass .
Here, is_subclass1 P C C' is true if C' is the name of the direct superclass of C. Then is_subclass is defined to be the transitive closure of is_subclass1.
For code generation to work, it is crucial that is_subclass1 has the mode i ⇒ i ⇒ o ⇒ bool, because otherwise the transitive closure cannot be computed. In the case of is_subclass1 this is easy, as a class has at most a single direct superclass, and the name of the superclass can thus be uniquely determined from the inputs.
However, for the subtype relation I also need to consider the interfaces that a class might implement:
inductive is_subtype1 :: "program ⇒ class_name ⇒ class_name ⇒ bool" for P :: program where
― ‹Same as subclass relation, no problem›
"⟦
Ok cl = lookup_class P C;
Some C' = (class_def.super cl)
⟧ ⟹ is_subtype1 P C C'" |
"⟦
Ok cl = lookup_class P C;
― ‹HERE IS THE PROBLEM: C' cannot be uniquely derived from the inputs and can thus not be marked as an output›
C' ∈ set (class_def.interfaces cl)
⟧ ⟹ is_subtype1 P C C'"
The problem is that there are multiple possible values for C' and that it cannot be marked as an output.
Intuitively, I think this should not be a problem for the code generator, as the generated code could just iterate over all the interfaces of a class. However, I don't know if this can be expressed in Isabelle/HOL.
Thus, the question is: Is there a way to generate code for is_subtype1 with mode i ⇒ i ⇒ o ⇒ bool?
You can solve your problem by importing HOL-Library.Predicate_Compile_Alternative_Defs and then using List.member _ _ instead of _ ∈ set _.
There is an example of code_pred usage in "Concrete Semantics" by Tobias Nipkow and Gerwin Klein, Section 7.2.2. I've implemented a simple language based on the examples and I try to calculate values of expressions:
theory BooLang
imports Main
begin
type_synonym id = string
type_synonym 'a Env = "id ⇒ 'a"
datatype BooBoolExp =
BooLiteralExp bool |
BooLetExp id BooBoolExp BooBoolExp |
BooVarExp id |
BooAndExp BooBoolExp BooBoolExp
datatype BooVal = Bv bool
type_synonym BooEnv = "BooVal Env"
inductive tbooval :: "BooBoolExp × BooEnv ⇒ BooVal ⇒ bool" (infix "⇒" 55) where
Literal: "(BooLiteralExp b, env) ⇒ Bv b" |
And: "⟦(a, env) ⇒ Bv av; (b, env) ⇒ Bv bv⟧ ⟹ (BooAndExp a b, env) ⇒ Bv (av ∧ bv)" |
Var: "(BooVarExp v, env) ⇒ env v" |
Let: "⟦(val, env) ⇒ b; (body, env(v := b)) ⇒ x⟧ ⟹ (BooLetExp v val body, env) ⇒ x"
code_pred tbooval .
values "{t. True}"
values "{t. (BooLiteralExp true, λ_. Bv false) ⇒ t}"
end
But for the 1st values' invocation I get the error:
Evaluation with values is not possible because compilation with
code_pred was not invoked.
And for the 2nd one I get the error:
No mode possible for comprehension {t. (BooLiteralExp true, λ_. Bv
false) ⇒ t}.
What's wrong with my theory?
The first command values {t. True} cannot work as this command asks Isabelle to enumerate all values of the type of t, which is inferred to be a type variable 'a; and this cannot be done.
For the second command, you just misspelled True and False. As is, true and false are inferred to be boolean variables instead of boolean constants. Unlike value, the command values does not support symbolic execution in Isabelle2016-1. That is, all input arguments to the inductive predicate must be ground values without variables. In your example, code_pred infers two execution modes: One in which everything is given as input and one in which only the first argument is given as input. You can see the inferred modes by passing the [show_modes] option as in
code_pred [show_modes] tboolval .
You can find some further documentation on code_pred and values in the code generator tutorial.
This (trimmed out) corecursive function definition in Isabelle
primcorec tree :: "'form fset ⇒ 'vertex ⇒ 'preform ⇒ (('form fset × 'form), ('rule × 'preform) NatRule) dtree" where
"tree Γ v p =
(case undefined of Hyp h c ⇒ undefined | Reg c ⇒
Node undefined (fimage (tree Γ v) undefined)
)"
yields
Unexpected corecursive call in "case undefined of Reg c ⇒ Node undefined (tree Γ v |`| undefined)" at
"case case undefined of Reg c ⇒ Node undefined (tree Γ v |`| undefined) of Node uu uua ⇒ uua"
but if I simplify it further to
primcorec tree :: "'form fset ⇒ 'vertex ⇒ 'preform ⇒ (('form fset × 'form), ('rule × 'preform) NatRule) dtree" where
"tree Γ v p =
(Node undefined (fimage (tree Γ v) undefined))"
it works.
I also tried to use the deconstructor view, i.e.
primcorec tree :: "'form fset ⇒ 'vertex ⇒ 'preform ⇒ (('form fset × 'form), ('rule × 'preform) NatRule) dtree" where
"cont (tree Γ v p) = (case undefined of Hyp h c ⇒ undefined | Reg c ⇒ (fimage (tree Γ v) undefined))"
And now I get a different error message: Invalid map function at "case undefined of Reg c ⇒ tree Γ v |`| undefined".
What might be the cause?
With other case expressions it works, and I don’t find any mention of a restriction in the documentation (§ 5.1.1 in the datatype documentation.)
Via private communication I was told that the solution is to add the (discs_sel) option to the datatype wher the Hyp constructor comes from.
I am new to Isabelle and this is a simplification of my first program
theory Scratch
imports Main
begin
record flow =
Src :: "nat"
Dest :: "nat"
record diagram =
DataFlows :: "flow set"
Transitions :: "nat set"
Markings :: "flow set"
fun consume :: "diagram × (nat set) ⇒ (flow set)"
where
"(consume dia trans) = {n . n ∈ (Markings dia) ∧ (∃ t ∈ trans . (Dest n) = t)}"
end
The function give the error:
Type unification failed: Clash of types "_ ⇒ " and " set"
Type error in application: operator not of function type
Operator: consume dia :: flow set
Operand: trans :: (??'a × ??'a) set ⇒ bool
What should I do for the the code to compile?
First of all, you give two parameters to your consume function, but the way you defined its type, it takes a single tuple. This is unusual and often inconvenient – defined curried functions instead, like this:
fun consume :: "diagram ⇒ (nat set) ⇒ (flow set)"
Also, trans is a constant; it is the property that a relation is transitive. You can see that by observing that trans is black to indicate that it is a constant and the other variable is blue, indicating that it is a free variable.
I therefore recommend using another name, like ts:
where
"consume dia ts = {n . n ∈ (Markings dia) ∧ (∃ t ∈ ts . (Dest n) = t)}"