module Data.Fin.CaseBash where
The case bash tacticπ
In the 1Lab, we try to strive for the most elegant proofs possible. Unfortunately, sometimes the most elegant proof really is a giant proof-by-cases. These proofs are enlightening to read and tedious to write, and are a prime candidate for proof automation.
Enter case-bash!
. This tactic
walks down a goal like
and repeatedly case splits on each listable
type in the domain, and which point it gathers all of the resulting
goals into a dependent list.
Somewhat surprisingly, this can be implemented entirely using
instance arguments! We first use the Curried
typeclass to gather all of the
arguments into a big Ξ£ type. We then use instance resolution to try and
find a Listing
of that Ξ£-type,
which will attempt to resolve Listing
instances for all of the
components. We then require proofs of the curried codomain for every
single element in the listing of the curried codomain.
case-bash!: β {β βd βf} {Goal : Type β}
β β¦ C : Curried Goal βd βf β¦
β β¦ ds : Listing (Curried.Dom C) β¦
β All (Curried.Cod C) (Listing.univ ds)
β Goal
The type of the function is honestly more complicated then itβs implementation, which just curries and then looks up proofs in a list.
=
case-bash! β¦ C β¦ β¦ ds β¦ proofs .to (Curried.eqv C) (Ξ» ix β all-β proofs (Listing.find ds ix)) Equiv
Examplesπ
Now that we have our tactic, letβs see some examples. The following
bit of code proves commutativity of and
via case-bash!
.
private
: β (x y : Bool) β and x y β‘ and y x
and-comm-via-case-bash = case-bash! (refl β· refl β· refl β· refl β· []) and-comm-via-case-bash
We can avoid writing a giant list of refl
by using even more proof automation.
The decide!
tactic lets us use
Dec
instances to prove goals, and
All
has a Dec
instance that tries to decide some
predicate for every element of the list. This means that we can combine
case-bash!
and decide!
to discharge the entire list of
goals in one go, provided that every goal is decidable.
private
: β (x y z : Bool) β and x (and y z) β‘ and (and x y) z
and-assoc-via-case-bash = case-bash! decide! and-assoc-via-case-bash