[Agda] Proofs for enumerated types
Gregory Crosswhite
gcross at phys.washington.edu
Mon Sep 13 20:36:17 CEST 2010
Yay, I knew that there had to be a way to do this! :-) Is anyone
working on a library that could automate much of this? I'm thinking
along the lines of a module parametrized by something like (LeftInverse
s (P.setoid (Fin n))) that would automatically provide _≟_, as well as
functions that could take properties on functions in the s setoid and
decide them by transferring the function and property to Fin n,
performing the decision there, and then lifting this result back to a
result in s. If not, I am thinking of playing around with writing such
a module myself, though my agda-fu is weak. :-)
Cheers,
Greg
On 09/11/10 12:02, Nils Anders Danielsson wrote:
> On 2010-09-10 23:01, Gregory Crosswhite wrote:
>> However, I feel like there should be a more elegant way of doing this.
>> Since the type is a set that only contains a finite number of values,
>> such properties as associativity, commutativity, existence of an inverse
>> (I), etc. can be proven by performing a brute-force examination of all
>> the possibilities. There is probably a way to do this somewhere in the
>> standard libraries [...]
>
> Indeed there is:
>
> module Pauli where
>
> import Algebra.FunctionProperties
> open import Data.Fin
> open import Data.Fin.Props using (eq?)
> open import Data.Fin.Dec using (all?)
> open import Function
> open import Function.LeftInverse
> open import Relation.Binary.PropositionalEquality as P
> open import Relation.Nullary
>
> data Pauli : Set where
> I X Y Z : Pauli
>
> infixl 7 _⋅_
>
> _⋅_ : Pauli → Pauli → Pauli
> _ ⋅ I = I
> I ⋅ _ = I
> X ⋅ X = I
> X ⋅ Y = Z
> X ⋅ Z = Y
> Y ⋅ X = Z
> Y ⋅ Y = I
> Y ⋅ Z = X
> Z ⋅ X = Y
> Z ⋅ Y = X
> Z ⋅ Z = I
>
> -- Injection into Fin 4.
>
> to : Pauli → Fin 4
> to I = # 0
> to X = # 1
> to Y = # 2
> to Z = # 3
>
> from : Fin 4 → Pauli
> from zero = I
> from (suc zero) = X
> from (suc (suc zero)) = Y
> from (suc (suc (suc zero))) = Z
> from (suc (suc (suc (suc ()))))
>
> finite : LeftInverse (P.setoid Pauli) (P.setoid (Fin 4))
> finite = record
> { to = P.→-to-⟶ to
> ; from = P.→-to-⟶ from
> ; left-inverse-of = from∘to
> }
> where
> from∘to : ∀ x → from (to x) ≡ x
> from∘to I = refl
> from∘to X = refl
> from∘to Y = refl
> from∘to Z = refl
>
> -- Deciding equality is easy for finite sets.
>
> infix 4 _≟_
>
> _≟_ : (p₁ p₂ : Pauli) → Dec (p₁ ≡ p₂)
> _≟_ = eq? (LeftInverse.injection finite)
>
> -- Proving that a commutative operation actually is commutative is
> -- also easy. We can start by deciding whether the operator, lifted to
> -- Fin 4, is commutative.
>
> private
>
> _○_ = _⋅_ on from
>
> ○-comm? : Dec (∀ x y → (x ○ y) ≡ (y ○ x))
> ○-comm? = all? λ x → all? λ y → (x ○ y) ≟ (y ○ x)
>
> -- If we evaluate ○-comm? we see that the answer is yes <something>.
> -- Let's extract this <something> and polish it a bit.
>
> fromYes : ∀ {P : Set} (x : Dec P) {p} → x ≡ yes p → P
> fromYes .(yes p) {p} refl = p
>
> open Algebra.FunctionProperties {A = Pauli} _≡_
>
> ⋅-comm : Commutative _⋅_
> ⋅-comm x y =
> P.subst (λ y → x ⋅ y ≡ y ⋅ x)
> (LeftInverse.left-inverse-of finite y) $
> P.subst (λ x → x ⋅ from (to y) ≡ from (to y) ⋅ x)
> (LeftInverse.left-inverse-of finite x) $
> fromYes ○-comm? refl (to x) (to y)
>
> --
> /NAD
>
More information about the Agda
mailing list