简体   繁体   中英

Agda Theorems for Powers

I'm trying to prove the following:

1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc x} = {!!}  

I'm brand new to Adga and don't even really know where to start. Any suggestions or guidance? Obviously very easy to prove on paper but I am unsure of what to tell Agda.

I defined my pow function as follows:

_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc zero) = x
x pow (suc y) = x * (x pow y)

When you pattern match on n in 1-pow and find out it is zero , Agda will take a look at the definition of _pow_ and check if one of the function clauses matches. The first one does, so it will apply that definition and 1 pow zero becomes 1 . 1 is obviously equal to 1 , so refl will work for the proof.

What about the case when n was suc x ? Here's the problem: Agda cannot commit to the second clause (because x could be zero ) nor the third clause (because x could be suc y for some y ). So you have to go one step further to make sure Agda applies the definition of _pow_ :

1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero}        = refl
1-pow {suc zero}    = {!!}
1-pow {suc (suc x)} = {!!}

Let's check out what is the type of the first hole. Agda tells us it is 1 ≡ 1 , so we can use refl again. The last one is a bit trickier, we are supposed to produce something of type 1 * 1 pow (suc x) ≡ 1 . Assuming your are using the standard definition of _*_ (ie recursion on the left argument and repeated addition on the left side, such as the one in the standard library), this should reduce to 1 pow (suc x) + 0 ≡ 1 . Induction hypothesis (that is, 1-pow applied to suc x ) tells us that 1 pow (suc x) ≡ 1 .

So we are almost there, but we don't know that n + 0 ≡ n (that's because addition is defined by recursion on the left argument, so we can't simplify this expression). One option is to prove this fact, which I leave as an exercise. Here's a hint, though: you might find this function useful.

cong : ∀ {a b} {A : Set a} {B : Set b}
       (f : A → B) {x y} → x ≡ y → f x ≡ f y
cong f refl = refl

It's already part of the Relation.Binary.PropositionalEquality module, so you don't need to define it yourself.

So, to recap: we know that n + 0 ≡ n and 1 pow (suc x) ≡ 1 and we need 1 pow (suc x) + 0 ≡ 1 . These two facts fit together quite nicely - the equality is transitive, so we should be able to merge 1 pow (suc x) + 0 ≡ 1 pow (suc x) and 1 pow (suc x) ≡ 1 into one proof and indeed, this is the case:

1-pow {suc (suc x)} = trans (+0 (1 pow suc x)) (1-pow {suc x})

And that's it!


Let me mention few other approaches.

The whole proof could also be done using a proof that 1 * x ≡ x , though this is hardly different from what we did before.

You could simplify _pow_ to:

_pow_ : ℕ → ℕ → ℕ
x pow zero    = 1
x pow (suc y) = x * (x pow y)

This is slightly more convenient to work with. The proof would be changed accordingly (ie it wouldn't have the second clause of the original proof).

And lastly, you could do this:

1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero}        = refl
1-pow {suc zero}    = refl
1-pow {suc (suc x)} = cong (λ x → x + 0) (1-pow {suc x})

Try to figure out why that works! If you have any problems, let me know in the comments and I'll help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM