Skip to main content

Implication (==>)

The implication operator expresses conditional relationships in specifications: "if A then B". It is a proof/specification operator, not a general runtime boolean operator.

Syntax​

condition ==> consequence

The expression a ==> b is true when:

  • a is false (the condition doesn't hold, so the implication is vacuously true)
  • Both a and b are true

It is logically equivalent to not a or b.

==> is accepted in ghost contexts such as contracts, static assert, loop:invariant, pure functions, and lemmas. Runtime expressions should use ordinary if, and, or, and not.

Using Implication in Contracts​

Implication is most useful in ensures clauses to express conditional postconditions. Rather than stating what always holds, you state what holds under specific circumstances.

public func sign(x : Int) : async Int
ensures x >= 0 ==> result >= 0;
ensures x < 0 ==> result < 0;
{
if (x >= 0) { x } else { x }
};

This contract says:

  • If the input is non-negative, the result is non-negative
  • If the input is negative, the result is negative

Using Implication in Assertions​

You can use implication inside assert statements to verify logical properties:

public func checkBounds(x : Nat) : async Bool {
assert x > 10 ==> x > 5; // If x > 10, then certainly x > 5
x > 10
};

This means static verification assertions. runtime:assert is executable code and cannot use ==>.

Common Patterns​

Guarding Division​

Use implication to specify behavior that depends on a condition:

public func safeDivide(a : Int, b : Int) : async Int
entry_requires b != 0;
requires b != 0;
ensures b > 0 ==> (a >= 0 ==> result >= 0);
{
a / b
};

Conditional State Changes​

Express that a change only happens under certain conditions:

public func maybeIncrement(doIt : Bool) : async ()
modifies counter
ensures doIt ==> counter == old(counter) + 1;
ensures not doIt ==> counter == old(counter);
{
if (doIt) { counter += 1 };
};

Chained Implications​

Multiple implications can express complex conditional logic:

public func classify(n : Nat) : async Nat
ensures n < 10 ==> (n < 5 ==> result == 0);
ensures n < 10 ==> (n >= 5 ==> result == 1);
ensures n >= 10 ==> result == 2;
{
if (n < 5) { 0 }
else if (n < 10) { 1 }
else { 2 }
};

Precedence​

The ==> operator has lower precedence than and and or. This means:

a and b ==> c    // Parsed as: (a and b) ==> c
a ==> b or c // Parsed as: a ==> (b or c)

Use parentheses when the default precedence isn't what you want:

a ==> (b and c)  // Implication to a conjunction
(a ==> b) and c // Conjunction of an implication and c

The operator is non-associative, so chaining requires explicit parentheses:

// This is rejected:
// a ==> b ==> c

// Use explicit grouping:
a ==> (b ==> c) // If a, then (if b then c)
(a ==> b) ==> c // If (a implies b), then c

Truth Table​

aba ==> b
falsefalsetrue
falsetruetrue
truefalsefalse
truetruetrue

Summary​

  • a ==> b means "if a then b", equivalent to not a or b
  • Use in ensures clauses for conditional postconditions
  • Only available in ghost/specification contexts
  • Lower precedence than and/or, non-associative
  • Vacuously true when the antecedent is false