Prova por aplicação

A nossa primeira ferramenta para resolver provas que não são reduzíveis de cara será a aplicação dos dois lados. Para isso, usaremos a função Equal.apply, que recebe uma igualdade (um Equal) e uma função, e aplica essa função dos dois lados da igualdade, gerando uma nova igualdade.

Por exemplo:

Example_apply (n: Nat) (m: Nat) (e: Equal Nat m n) : Equal Nat (Nat.succ m) (Nat.succ n)
Example_apply n m e = ?

O que exatamente temos aqui? Temos uma prova que recebe como argumento uma outra prova/igualdade. Isso quer dizer que vamos realizar a nossa prova supondo que a prova dada como argumento também é verdadeira. Então, lendo a declaração da prova, temos que: "Dados dois naturais, m e n, e uma prova de que eles são iguais, provar que Nat.succ m e Nat.succ n também são iguais".

Nós aprendemos, nas nossas aulas de matemática, que aplicar uma função dos dois lados de uma igualdade mantém a igualdade (x/2 = 3 -> 2*x/2 = 2*3), e podemos ver que para provar o que a gente quer, precisamos aplicar a função Nat.succ nos dois lados de e, usando Equal.apply

+ INFO  Inspection.

  • Expected: (Equal Nat (Nat.succ m) (Nat.succ n)) 

  • Context: 
  •   n : Nat 
  •   m : Nat 
  •   e : (Equal Nat m n) 

  Example_apply n m e = ?
                        ┬
                        └Here!

Como o Equal.apply funciona: Ele recebe como primeiro argumento a função a ser aplicada dos dois lados, e como segundo argumento a igualdade aonde aplicar a função. Se você não entendeu muito bem a passagem da função de argumento (x => Nat.succ x), ela é o que chamamos de função lambda, e é também conhecida como função anônima. Funções lambda são identificadas pela sua seta =>, sendo que do lado esquerdo da seta fica o nome do argumento da função - use o nome que quiser - e do lado direito fica o corpo da função: o que ela retorna. A nossa função lambda atual é uma função que recebe um x qualquer e retorna Nat.succ x.

Podemos ver o resultado disso dando check no arquivo:

+ INFO  Inspection.

  • Expected: (Equal Nat (Nat.succ m) (Nat.succ n)) 

  • Context: 
  •   n : Nat 
  •   m : Nat 
  •   e       : (Equal Nat m n) 
  •   e_apply : (Equal Nat (Nat.succ m) (Nat.succ n)) 
  •   e_apply = (Equal.apply Nat Nat m n (x => (Nat.succ x)) e) 

  let e_apply = Equal.apply (x => Nat.succ x) e
      ?
      ┬
      └Here!

Como e_apply é uma igualdade do tipo Equal Nat (Nat.succ m) (Nat.succ n), a prova que procuramos, é só retornar ele e concluiremos a nossa prova.

Example_apply (n: Nat) (m: Nat) (e: Equal Nat m n) : Equal Nat (Nat.succ m) (Nat.succ n)
Example_apply n m e =
  let e_apply = Equal.apply (x => Nat.succ x) e
  e_apply
  All terms checked.