[Agda] Computation and patterns in called functions
Nils Anders Danielsson
nad at chalmers.se
Mon Jan 28 16:24:16 CET 2013
On 2013-01-28 13:35, Francesco Mazzoli wrote:
> I frequently encounter a nasty problem when having to prove properties about
> functions with that pattern match only on certain constructors, since in the
> proof I have to consider every possible case for the terms to compute. I think
> that an heuristic that checks whether the matched constructors have been matched
> already and takes the last branch otherwise would be very useful - or maybe
> there is already a solution that I’m not aware of.
There are several solutions:
* One could perhaps change Agda so that overlapping patterns are
replaced with non-overlapping ones before the right-hand sides are
type-checked. (I believe that Coq does this.) For instance,
_≟_ : (x y : Bool) → Dec (x ≡ y)
true ≟ true = yes refl
false ≟ false = yes refl
_ ≟ _ = no (λ ())
could be expanded into the following, type-correct code:
_≟_ : (x y : Bool) → Dec (x ≡ y)
true ≟ true = yes refl
false ≟ false = yes refl
true ≟ false = no (λ ())
false ≟ true = no (λ ())
However, it's not quite clear to me what would happen if a duplicated
right-hand side contained a goal.
* One can use custom eliminators or views. Example (based on your code):
data OptExpP : Exp → Set where
plus-const-0 : ∀ e → OptExpP (plus (const 0) e)
plus : ∀ e₁ e₂ → e₁ ≢ const 0 → OptExpP (plus e₁ e₂)
anything-else : ∀ e → ¬ (∃₂ λ e₁ e₂ → e ≡ plus e₁ e₂) → OptExpP e
optExpP : ∀ e → OptExpP e
optExpP (const n) = anything-else (const n) (λ { (_ , _ , ()) })
optExpP (var x) = anything-else (var x) (λ { (_ , _ , ()) })
optExpP (plus (const zero) e) = plus-const-0 e
optExpP (plus (const (suc n)) e) = plus (const (suc n)) e (λ ())
optExpP (plus (var x) e) = plus (var x) e (λ ())
optExpP (plus (plus e₁ e₂) e₃) = plus (plus e₁ e₂) e₃ (λ ())
optExp : Exp → Exp
optExp e with optExpP e
optExp .(plus (const 0) e) | plus-const-0 e = optExp e
optExp .(plus e₁ e₂) | plus e₁ e₂ _ = plus (optExp e₁) (optExp e₂)
optExp .e | anything-else e _ = e
optExp-correct : ∀ {vs} e → evalExp vs e ≡ evalExp vs (optExp e)
optExp-correct e with optExpP e
optExp-correct .(plus (const 0) e) | plus-const-0 e = optExp-correct e
optExp-correct .(plus e₁ e₂) | plus e₁ e₂ _ = cong₂ _+_ (optExp-correct e₁) (optExp-correct e₂)
optExp-correct .(const x) | anything-else (const x) _ = refl
optExp-correct .(var x) | anything-else (var x) _ = refl
optExp-correct .(plus e₁ e₂) | anything-else (plus e₁ e₂) p = ⊥-elim (p (e₁ , e₂ , refl))
--
/NAD
More information about the Agda
mailing list