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.