Source code on Github# Ring solver
`solve-≈` proves equalities that hold in any commutative semiring or
commutative ring. It is a practical, reflection-based frontend to the
standard library's `Algebra.Solver.Ring`.
This file is literate Agda. The implementation lives in
`Tactic.Solver.Ring.Core`; here we only define the macro, so that
jumping to its definition lands on this documentation.
The solver handles both `CommutativeSemiring` and `CommutativeRing`,
see below.
```agda
{-# OPTIONS --without-K --safe #-}
module Tactic.Solver.Ring where
open import Algebra using (CommutativeSemiring; CommutativeRing)
open import Reflection using (Term; TC)
open import Data.Unit using (⊤)
open import Relation.Binary.PropositionalEquality using (_≡_)
open import Tactic.Solver.Ring.Core using (solve-≈-macro)
macro
solve-≈ : Term → Term → TC ⊤
solve-≈ = solve-≈-macro
```
# Examples
## A first example: ℕ
Pass the bundle whose operations appear in the goal; `∀`-bound
variables are handled.
```agda
module ℕ-example where
open import Data.Nat using (ℕ; _+_; _*_)
open import Data.Nat.Properties using (+-*-commutativeSemiring)
distrib : ∀ a b c → (a + b) * c ≡ (c * a) + (c * b)
distrib a b = solve-≈ +-*-commutativeSemiring
```
## Rings: subtraction and negation
A `CommutativeRing` bundle additionally lets the goal use `_-_` and
`-_`.
```agda
module ℤ-example where
open import Data.Integer using (ℤ; _+_; _*_; _-_; -_)
open import Data.Integer.Properties using (+-*-commutativeRing)
difference-of-squares : ∀ a b → (a - b) * (a + b) ≡ a * a - b * b
difference-of-squares a b = solve-≈ +-*-commutativeRing
negation : ∀ a b → - (a + b) ≡ - a - b
negation a b = solve-≈ +-*-commutativeRing
```
## Literals
Each carrier's numeric literals are recognised as ring constants —
`0`/`1` on ℕ, `+ n` on ℤ, `0ℚ`/`1ℚ` on ℚ.
```agda
module ℚ-example where
open import Data.Rational using (ℚ; 0ℚ; 1ℚ; _+_; _*_)
import Data.Rational.Properties as ℚP
unit : ∀ q → q * 1ℚ ≡ q
unit q = solve-≈ ℚP.+-*-commutativeRing
zero : ∀ q → (q + 0ℚ) * 1ℚ ≡ q
zero q = solve-≈ ℚP.+-*-commutativeRing
```
## Abstract bundles
The carrier need not be concrete; under an abstract bundle, state the
goal with its `_≈_`.
```agda
module abstract-example {c ℓ} (R : CommutativeSemiring c ℓ) where
open CommutativeSemiring R
rearrange : ∀ a b c d → ((a + b) + (c + d)) ≈ ((d + c) + (b + a))
rearrange a b c d = solve-≈ R
```
## Scope and limitations
- The goal's relation may be the bundle's `_≈_`, or propositional
`_≡_` when that is the bundle's equality (as for ℕ/ℤ/ℚ).
- Subterms the solver does not recognise as ring syntax become opaque
*atoms*: it proves the goal treating them as fresh variables, so an
identity that depends on their internal structure will not be found.
- Carriers that are themselves function types (with a pointwise
`_≈_`) are not supported.
`Tactic.Solver.Ring.Tests.*` exercises many more goals and bundle
shapes.