2017-01-21 9 views
5

J'essaie d'utiliser la syntaxe pour les types de données inductifs mais j'ai reçu un message d'erreur "les types mutuellement inductifs doivent compiler au type inductif de base avec élimination dépendante".Comment définir des propositions inductives mutuelles dans Lean?

est Ci-dessous un exemple de ma tentative de définir des propositions even et odd sur des nombres naturels

mutual inductive even, odd 
with even: ℕ → Prop 
| z: even 0 
| n: ∀ n, odd n → even (n + 1) 
with odd: ℕ → Prop 
| z: odd 1 
| n: ∀ n, even n → odd (n + 1) 

également une question connexe: Quelle est la syntaxe pour définir des fonctions mutuellement récursives? Je n'arrive pas à le trouver documenté nulle part.

Répondre

5

Je pense que Lean est automatiquement essayer de créer les recursors even.rec et odd.rec à travailler avec Type, non Prop. Mais cela ne fonctionne pas parce que Lean sépare le monde logique (Prop) et le monde de calcul (Type). En d'autres termes, nous pouvons détruire un terme logique (preuve) uniquement pour produire un terme logique. Observez, que votre exemple fonctionnerait si vous avez fait even et odd de type ℕ → Type. L'assistant de preuve Coq, qui est un système apparenté, gère automatiquement cette situation en créant deux principes d'induction (plutôt faibles et peu pratiques), mais il ne génère pas les récurrents généraux, bien sûr.

Il existe une solution de contournement, décrite dans cette section Lean wiki article. Il implique d'écrire beaucoup de passe-partout. Permettez-moi de donner un exemple de comment cela pourrait être fait pour ce cas. En premier lieu, nous compilons les types inductifs mutuels dans une famille inductive. Nous ajoutons un index booléen représentant équitabilité:

inductive even_odd: bool → ℕ → Prop 
| ze: even_odd tt 0 
| ne: ∀ n, even_odd ff n → even_odd tt (n + 1) 
| zo: even_odd ff 1 
| no: ∀ n, even_odd tt n → even_odd ff (n + 1) 

Ensuite, nous définissons quelques abréviations pour simuler les types mutuellement inductives:

-- types 
def even := even_odd tt 
def odd := even_odd ff 

-- constructors 
def even.z : even 0 := even_odd.ze 
def even.n (n : ℕ) (o : odd n): even (n + 1) := even_odd.ne n o 
def odd.z : odd 1 := even_odd.zo 
def odd.n (n : ℕ) (e : even n): odd (n + 1) := even_odd.no n e 

Maintenant, nous allons déployer nos propres principes d'induction:

-- induction principles 
def even.induction_on {n : ℕ} (ev : even n) (Ce : ℕ → Prop) (Co : ℕ → Prop) 
         (ce0 : Ce 0) (stepe : ∀ n : ℕ, Co n → Ce (n + 1)) 
         (co1 : Co 1) (stepo : ∀ n : ℕ, Ce n → Co (n + 1)) : Ce n := 
    @even_odd.rec (λ (switch : bool), bool.rec_on switch Co Ce) 
       ce0 (λ n _ co, stepe n co) 
       co1 (λ n _ ce, stepo n ce) 
       tt n ev 

def odd.induction_on {n : ℕ} (od : odd n) (Co : ℕ → Prop) (Ce : ℕ → Prop) 
        (ce0 : Ce 0) (stepe : ∀ n : ℕ, Co n → Ce (n + 1)) 
        (co1 : Co 1) (stepo : ∀ n : ℕ, Ce n → Co (n + 1)) := 
    @even_odd.rec (λ (switch : bool), bool.rec_on switch Co Ce) 
       ce0 (λ n _ co, stepe n co) 
       co1 (λ n _ ce, stepo n ce) 
       ff n od 

Il serait préférable de faire le Ce : ℕ → Prop paramètre de even.induction_on implicite, mais pour une raison quelconque Lean ne peut pas en déduire (voir le lemme à la fin, wher e nous devons passer explicitement Ce, sinon Lean déduit Ce sans rapport avec notre objectif). La situation est symétrique avec odd.induction_on.

Quelle est la syntaxe pour définir les fonctions mutuellement récursives?

Comme expliqué dans ce lean-user thread, le soutien aux fonctions mutuellement récursives est très limité:

il n'y a pas de soutien pour les fonctions mutuellement récursives arbitraires, mais il y a un soutien pour un cas très simple. Après avoir défini un type mutuellement récursif, nous pouvons définir des fonctions mutuellement récursives qui "reflètent" la structure de ces types.

Vous pouvez trouver un exemple dans ce fil de discussion.Mais, encore une fois, nous pouvons simuler des fonctions mutuellement récursives en utilisant la même approche add-a-switching-parameter. Nous allons simuler mutuellement récursives prédicats booléens evenb et oddb:

def even_oddb : bool → ℕ → bool 
| tt 0  := tt 
| tt (n + 1) := even_oddb ff n 
| ff 0  := ff 
| ff (n + 1) := even_oddb tt n 

def evenb := even_oddb tt 
def oddb := even_oddb ff 

Voici un exemple de la façon dont tous les ci-dessus peut être utilisé. Prouvons un simple lemme:

lemma even_implies_evenb (n : ℕ) : even n -> evenb n = tt := 
    assume ev : even n, 
    even.induction_on ev (λ n, evenb n = tt) (λ n, oddb n = tt) 
    rfl 
    (λ (n : ℕ) (IH : oddb n = tt), IH) 
    rfl 
    (λ (n : ℕ) (IH : evenb n = tt), IH)