The syntax of CHR rules is the following:

rules::= rule rules
rules::= empty
rule::= name actual_rule pragma .
name::= atom @
name::= empty
actual_rule::= simplification_rule
actual_rule::= propagation_rule
actual_rule::= simpagation_rule
simplification_rule::= head <=> guard body
propagation_rule::= head ==> guard body
simpagation_rule::= head \ head <=> guard body
head::= constraints
constraints::= constraint constraint_id
constraints::= constraint constraint_id , constraints
constraint::= compound_term
constraint_id::= empty
constraint_id::= # variable
guard::= empty
guard::= goal disj
body::= goal
pragma::= empty
pragma::= pragma actual_pragmas
actual_pragmas::= actual_pragma
actual_pragmas::= actual_pragma , actual_pragmas
actual_pragma::= passive(variable)
disj::= ; | | { read as ; unless | is declared infix }

Note that the guard of a rule may not contain any goal that binds a variable in the head of the rule with a non-variable or with another variable in the head of the rule. It may however bind variables that don’t appear in the head of the rule, e.g. an auxiliary variable introduced in the guard.

Note also that, unless | has been declared as an operator, | and ; are indistinguishable as infix operators—both are read as ; (see ref-syn-syn-sen). So if e.g. a simplification rule is given as:

head <=> (P ; Q)

CHR will break the ambiguity by treating P as the guard and Q as the body, which is probably not what you want. To get the intended interpretation, you must supply a dummy guard ‘true |’:

head <=> true | (P ; Q)

Please note: the above is true as long as you don’t declare | as an infix operator, which is possible since release 4.3 for ISO compliance. Declaring | as an infix operator will confuse CHR.

Send feedback on this subject.