# Infix relation transformer syntax in Isabelle

Given

notation rtranclp ("(_^**)" [1000] 1000)

I can write, given an infix op ⇒

"op ⇒⇧*⇧* x x'"

but not the much more readable and prettier

"x ⇒⇧*⇧* x'"

I know that for every concrete relation (⇒ in this case), I can set up an abbreviation for this. But can I also solve this generally, i.e. for any infix relation?

If yes, can I extend that to multiple relations and other arguments? For example, given two infix relations ⇒ and ▹, and another term y I want to set it up so that I can write

x (⇒;▹)⇗y⇖ x'

(note the infix use) instead of

foo op ⇒ op ▹ y x x'

(where, in my case, has type foo :: ('a ⇒ 'a ⇒ bool) ⇒ ('a ⇒ 'b ⇒ bool) ⇒ 'b ⇒ 'a ⇒ 'a).

## Answers

I believe that a general solution for all infix relations is not possible, because the parser does not know about the relation symbols in isolation. As can be seen from the implementation in mixfix.ML, an infix declaration with relation symbol < is equivalent to two mixfix declarations, namely "op <" and "(_ < _)" with appropriate precedences.

However, there is a more generic and elegant solution than to introduce abbreviations for all combinations of predicates and predicate transformers. First, introduce a syntactic category for relational symbols. To also get the right output, add a syntactic marker _infix

nonterminal rel syntax (output) "_infix" :: "rel ⇒ logic" ("_")

Then, declare a syntax constant _rtranclp_rel for infix use with infix relations.

syntax "_rtranclp_rel" :: "logic ⇒ rel ⇒ logic ⇒ logic" ("(_ _⇧*⇧* _)") translations "_rtranclp_rel x R y" ⇀ "CONST rtranclp R x y" translations "_rtranclp_rel x (_infix R) y" ↽ "CONST rtranclp R x y"

Now, add a syntax translation to your relation rel that you want to use with _rtranclp_rel:

consts rel :: "nat ⇒ nat ⇒ bool" (infix "⇒" 100) syntax "_rel_infix" :: rel ("⇒") translations "_rel_infix" ⇀ "CONST rel" translations "_rel_infix" ↽ "_infix (CONST rel)"

Then, Isabelle should be able to correctly parse and pretty-print x ⇒⇧*⇧* z. Note, however, that all fully applied instances of rtranclp are pretty-printed infix (e.g., rtranclp R x y, independent of whether the relation is an infix symbol.

This mechanism then also works for your function foo:

consts foo :: "('a ⇒ 'a ⇒ bool) ⇒ ('b ⇒ 'b ⇒ bool) ⇒ 'b ⇒ 'a ⇒ 'a ⇒ bool" syntax "_foo_rel" :: "logic ⇒ rel ⇒ rel ⇒ logic ⇒ logic ⇒ logic" ("_ '(_;_')⇗_⇖ _") translations "_foo_rel x R S y z" ⇀ "CONST foo R S x y z" translations "_foo_rel x (_infix R) (_infix S) y z" ↽ "CONST foo R S x y z"

Of course, the precedences in the mixfix annotations should be adjusted to sensible ones. It is even possible to do this recursively. For example:

syntax "_rtranclp_rel2" :: "rel ⇒ rel" ("_⇧*⇧*") translations "_rtranclp_rel2 R" ⇀ "CONST rtranclp R" translations "_rtranclp_rel2 (_infix R)" ↽ "_infix (CONST rtranclp R)" term "x (⇒⇧*⇧*;⇒)⇗y⇖ z"