levels
This commit is contained in:
@@ -27,9 +27,10 @@ Zum Beispiel ist `ℕ` der Typ der natürlichen Zahlen, `Prop` der Typ der logis
|
||||
Aussagen, und ein Ring ist ein Typ `(R : Type)` zusammen mit einer Instanz `[Ring R]`,
|
||||
die sagt, dass auf diesem Typ eine Ringstruktur besteht.
|
||||
|
||||
**Achtung**: Wie du aber gleich sehen wirst sind Typen und Mengen in Lean komplett
|
||||
unterschiedliche Sachen! (Und Mengen nehmen in Lean nicht die fundamentale Funktion
|
||||
ein, die sie in der Mathe innehaben.)
|
||||
**Achtung**: Wie du aber gleich sehen wirst sind Typen und Mengen in Lean unterschiedliche
|
||||
Sachen.
|
||||
|
||||
Hier ein kleines Beispiel zu Typen und Instanzen:
|
||||
"
|
||||
|
||||
Statement
|
||||
@@ -38,5 +39,11 @@ Statement
|
||||
ring
|
||||
|
||||
Hint (R : Type) (h : CommRing R) (a : R) (b : R) : a + b = b + a =>
|
||||
"Die Taktik `ring` funktioniert in jedem Typen,
|
||||
der mindestens eine Instanz `[Ring R]` hat."
|
||||
"
|
||||
Die Taktik `ring` funktioniert in jedem Typen,
|
||||
ist aber stärker, je nach Instanz auf dem Typen.
|
||||
|
||||
In Mathlib sind Instanzen `[CommSemiring ℕ]`, [CommRing ℤ]`, `[Field ℚ]`, etc. definiert.
|
||||
Die Taktik `ring` muss eine dieser Instanzen finden, die sagen, dass die Addition kommutative ist,
|
||||
damit das Lemma `add_comm` angewendet und die Aussage bewiesen werden kann.
|
||||
"
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
import Mathlib
|
||||
|
||||
set_option tactic.hygienic false
|
||||
|
||||
Game "TestGame"
|
||||
World "LeanStuff"
|
||||
Level 1
|
||||
|
||||
Title ""
|
||||
|
||||
Introduction
|
||||
"
|
||||
Dieses Kapitel führt ein paar Lean-spezifische Sachen ein, die du wissen solltest.
|
||||
|
||||
Mathematisch haben diese Sachen keinen Inhalt, aber es ist wichtig, dass du etwas
|
||||
verstehst wie Lean manche Sachen macht.
|
||||
|
||||
Als erstes geht es um implizite und explizite Argumente von Lemmas. **Explizite Argumente**
|
||||
schreibt man mit runden Klammern `()`, **impliziete Argumente** mit geschweiften `{}`.
|
||||
|
||||
Als implizit werden alle Argumente markiert, die Lean selbständig aus dem Kontext
|
||||
erschliessen und einfüllen kann.
|
||||
|
||||
Als Beispiel hier zweimal das gleiche Lemma, einmal ohne impliziten Argumenten und einmal mit
|
||||
```
|
||||
lemma not_or_of_imp' (A B : Prop) (h : A → B) : ¬A ∨ B := sorry
|
||||
|
||||
lemma not_or_of_imp {A B : Prop} (h : A → B) : ¬A ∨ B := sorry
|
||||
```
|
||||
|
||||
Hat man nun `g : C → D` dann braucht man diese Lemmas mit
|
||||
`have := not_or_of_imp g` oder `have := not_or_of_imp' C D g`.
|
||||
|
||||
Wie man sieht erschliesst Lean die impliziten Argumente automatisch und es wäre deshalb
|
||||
unnötig, diese jedes Mal explizit angeben zu müssen.
|
||||
|
||||
TODO
|
||||
(Trick mit `@not_or_of_imp` kann man sagen, dass man **alle** Argumente angeben möchte und mir
|
||||
`not_or_of_imp g (B := D)` könnte man ein spezifisches implizites Argument spezifizieren.
|
||||
Wenn man diese Tricks braucht, heisst das aber meistens, das etwas nicht optimal definiert
|
||||
ist.)
|
||||
|
||||
TODO
|
||||
Zudem gibt es noch Argumente in eckigen Klammern `[]`. Dies sind auch implizite
|
||||
Argumente, die aber von der **Instance Resolution** gefüllt werden sollen. Dies
|
||||
wird später kommen, aber ein typisches Beispiel ist `(S : Type _) [ring S]` was Lean
|
||||
sagt, es soll suchen gehen, ob es weiss, dass `S` ein Ring ist.
|
||||
"
|
||||
|
||||
open Set
|
||||
|
||||
Statement
|
||||
"TODO" : True := by
|
||||
trivial
|
||||
|
||||
NewTactics rw
|
||||
|
||||
#check not_not
|
||||
#check not_or_of_imp
|
||||
@@ -12,26 +12,40 @@ Title "Universen"
|
||||
|
||||
Introduction
|
||||
"
|
||||
In der Mathematik stösst man manchmal an Mengentheoretische Grenzen, und so auch in Lean.
|
||||
Ein weitere Syntax, den man in Lean abundzu sieht sind Universen.
|
||||
|
||||
Klassisch ist bekannt dass die \"Menge aller Mengen\" nicht existieren kann.
|
||||
Diese sind für Mathematiker erst einmal nicht so wichtig, und es reicht zu wissen,
|
||||
dass diese existieren.
|
||||
|
||||
Falls man an diese Grenzen stösst (z.B. in der Mengenlehre oder Kategorientheorie) hat Lean
|
||||
Universen bereit: `Type` ist eigentlich `Type 0` und es gibt auch `Type 1, Type 2, ...`
|
||||
Da alle Objekte in Lean einen Typ haben, kann man sich fragen, welchen Typ hat eigentlich `Type`
|
||||
selber? Die Anwort darauf ist dass `Type` vom Typ `Type 1` ist und dieses wiederum vom Typ `Type 2`
|
||||
usw.
|
||||
|
||||
Deshalb sieht man oft in Lean-Code `(R : Type _)` wenn es keine mengentheoretischen
|
||||
Probleme gibt (`_` ist ein Platzhalter) oder `universe u` am Anfang und dann `(R : Type u)`
|
||||
falls man diese mengentheoretischen Probleme kontrollieren muss.
|
||||
Da Lemmas in Lean gerne so algemein wie möglich formuliert werden, sieht man oft `(R : Type _)`
|
||||
anstatt `(R : Type)`, wobei `_` einfach ein Platzhalter für eine Zahl ist.
|
||||
|
||||
In der Praxis kommt man aber relativ weit, wenn man sich erst mal nicht mit Universen
|
||||
beschäftigt, und lediglich weiss, dass es sowas gibt.
|
||||
Alternativ kann man auch explizit Universum-Levels definieren, so sind die folgenden beiden
|
||||
Aussdrücke äquivalent:
|
||||
|
||||
```
|
||||
variable (R : Type _)
|
||||
|
||||
universe u
|
||||
variable (R : Type u)
|
||||
```
|
||||
|
||||
In der Praxis kann man immer ohne bedenken `Type _` verwendenen und wenn man auf
|
||||
(mengentheoretische)
|
||||
Probleme stösst, muss man dan eventuell die Universen spezifizieren.
|
||||
|
||||
*Die Normalform ist eigentlich `(R : Type _)` zu schreiben solange man kein Grund hat
|
||||
das Universum einzuschränken.*
|
||||
"
|
||||
|
||||
Statement
|
||||
"TODO"
|
||||
(R S : Type _) [CommRing R] (a b : R) : a + b = b + a := by
|
||||
""
|
||||
(R : Type _) [CommRing R] (a b : R) : a + b = b + a := by
|
||||
ring
|
||||
|
||||
Hint (R : Type _) (h : CommRing R) (a : R) (b : R) : a + b = b + a =>
|
||||
"Die Taktik `ring` funktioniert in jedem Typen,
|
||||
der mindestens eine Instanz `[Ring R]` hat."
|
||||
-- Hint (R : Type) (h : CommRing R) (a : R) (b : R) : a + b = b + a =>
|
||||
-- ""
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
import Mathlib
|
||||
import TestGame.Options.BigOperators
|
||||
|
||||
set_option tactic.hygienic false
|
||||
|
||||
@@ -20,38 +21,43 @@ schreibt man mit runden Klammern `()`, **impliziete Argumente** mit geschweiften
|
||||
Als implizit werden alle Argumente markiert, die Lean selbständig aus dem Kontext
|
||||
erschliessen und einfüllen kann.
|
||||
|
||||
Als Beispiel hier zweimal das gleiche Lemma, einmal ohne impliziten Argumenten und einmal mit
|
||||
Als Beispiel schauen wir uns ein bekanntes Lemma an:
|
||||
```
|
||||
lemma not_or_of_imp' (A B : Prop) (h : A → B) : ¬A ∨ B := sorry
|
||||
|
||||
lemma not_or_of_imp {A B : Prop} (h : A → B) : ¬A ∨ B := sorry
|
||||
lemma Fin.sum_univ_castSucc {β : Type _} [AddCommMonoid β] {n : ℕ} (f : Fin (n + 1) → β) :
|
||||
∑ i : Fin (n + 1), f i = ∑ i : Fin n, f (↑Fin.castSucc.toEmbedding i) + f (Fin.last n) := by
|
||||
sorry
|
||||
```
|
||||
|
||||
Hat man nun `g : C → D` dann braucht man diese Lemmas mit
|
||||
`have := not_or_of_imp g` oder `have := not_or_of_imp' C D g`.
|
||||
|
||||
Wie man sieht erschliesst Lean die impliziten Argumente automatisch und es wäre deshalb
|
||||
unnötig, diese jedes Mal explizit angeben zu müssen.
|
||||
|
||||
TODO
|
||||
(Trick mit `@not_or_of_imp` kann man sagen, dass man **alle** Argumente angeben möchte und mir
|
||||
`not_or_of_imp g (B := D)` könnte man ein spezifisches implizites Argument spezifizieren.
|
||||
Wenn man diese Tricks braucht, heisst das aber meistens, das etwas nicht optimal definiert
|
||||
ist.)
|
||||
|
||||
|
||||
Nebenbemerkung: Es gibt auch noch implizite **Klassen-Elemente** mit eckigen Klammern `[]`
|
||||
wie zum Beispiel `[CommRing R]` im vorigen Beispiel. Diese werden später behandelt,
|
||||
und sagen Lean, dass es für dieses Argument eine **Instanz** suchen gehen soll. Diese
|
||||
Instanzen werden mehrheitlich dafür verwendet, mathematische Strukturen auf Typen zu
|
||||
definieren, aber das kommt alles später.
|
||||
Hier ist unter anderem `n` als implizites Argument angegeben, da Lean aus `f` herauslesen kann,
|
||||
was `n` sein muss. Falls man trotzdem einmal das implizites Argument angeben muss
|
||||
(z.B. um `rw` zu helfen, wenn es mehrere Möglichkeiten gibt),
|
||||
kann man dies mit `Fin.sum_univ_castSucc (n := m + 1)` machen.
|
||||
"
|
||||
|
||||
Statement
|
||||
"TODO"
|
||||
(R S : Type _) [CommRing R] (a b : R) : a + b = b + a := by
|
||||
ring
|
||||
open BigOperators
|
||||
|
||||
Hint (R : Type _) (h : CommRing R) (a : R) (b : R) : a + b = b + a =>
|
||||
"Die Taktik `ring` funktioniert in jedem Typen,
|
||||
der mindestens eine Instanz `[Ring R]` hat."
|
||||
Statement
|
||||
"Zeige $(\\sum_{i=0}^{m} i) + (m + 1) = \\sum_{i=0}^{m + 1} i$."
|
||||
(m : ℕ) :
|
||||
∑ i : Fin (m + 1), (i : ℕ) + (m + 1) = ∑ i : Fin (Nat.succ m + 1), ↑i := by
|
||||
rw [Fin.sum_univ_castSucc (n := m + 1)]
|
||||
rfl
|
||||
|
||||
OnlyTactics rw rfl
|
||||
|
||||
NewLemmas Fin.sum_univ_castSucc
|
||||
|
||||
HiddenHint (m : ℕ) :
|
||||
∑ i : Fin (m + 1), (i : ℕ) + (m + 1) = ∑ i : Fin (Nat.succ m + 1), ↑i =>
|
||||
"Das Lemma `Fin.sum_univ_castSucc` hilft."
|
||||
|
||||
Hint (m : ℕ) :
|
||||
∑ i : Fin m, (Fin.castSucc.toEmbedding i : ℕ) + ↑(Fin.last m) + (m + 1) =
|
||||
∑ i : Fin (Nat.succ m + 1), ↑i =>
|
||||
"Hier hat `rw` die falsche der beiden Summen umgeschrieben. Hilf ihm mit
|
||||
`rw [Fin.sum_univ_castSucc (n := m + 1)]`."
|
||||
|
||||
Hint (m : ℕ) :
|
||||
∑ i : Fin (m + 1), (i : ℕ) + (m + 1) =
|
||||
∑ i : Fin (m + 1), ↑i + (m + 1) =>
|
||||
"Jetzt sind beide Seiten gleich und das Goal kann mit `rfl` geschlossen werden."
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
import Mathlib
|
||||
import TestGame.Options.BigOperators
|
||||
|
||||
set_option tactic.hygienic false
|
||||
|
||||
Game "TestGame"
|
||||
World "LeanStuff"
|
||||
Level 4
|
||||
|
||||
Title "Instanz-Argumente"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Bezüglich impliziten Argumente gibt es noch einige weitere Punkte oder Tricks,
|
||||
die man wissen sollte.
|
||||
|
||||
* Instanz-Argumente wie `[Ring R]` sind auch impilzite Argumente. Der Unterschied ist, dass
|
||||
Lean einen anderen Mechanismus braucht, um diese zu füllen: Es sucht nach einer entsprechenden
|
||||
*Instanz* und, setzt die erste solche Instanz ein.
|
||||
Ausserhalb eines Beweises könnte man auch mit
|
||||
```
|
||||
#synth Ring ℤ
|
||||
```
|
||||
testen, ob Lean eine ensprechende Instanz findet. Instanzen werden dafür gebraucht, Typen
|
||||
mit (algebraischer) Stukturen zu versehen.
|
||||
* Ein `_` irgendwo im Lean-Code ist immer ein Platzhalter, den Lean versucht aus dem Kontext zu
|
||||
füllen. Das kann praktisch sein, wenn man etwas nicht ausschreiben will, das offensichtlich ist.
|
||||
* Mit `@` kann man forcieren, dass alle Argumente explizit sind.
|
||||
Für ein Lemma
|
||||
```
|
||||
lemma not_or_of_imp {A B : Prop} (h : A → B) :
|
||||
¬A ∨ B := sorry
|
||||
```
|
||||
heisst das zum Beispiel dass `not_or_of_imp g` das gleiche ist wie
|
||||
`@not_or_of_imp _ _ g`.
|
||||
|
||||
Und `Fin.sum_univ_castSucc (n := m + 1)` könnte man auch als
|
||||
`@Fin.sum_univ_castSucc _ _ (m + 1)` schreiben.
|
||||
"
|
||||
|
||||
open BigOperators
|
||||
|
||||
Statement
|
||||
"Zeige $(\\sum_{i=0}^{m} i) + (m + 1) = \\sum_{i=0}^{m + 1} i$."
|
||||
(m : ℕ) :
|
||||
∑ i : Fin (m + 1), (i : ℕ) + (m + 1) = ∑ i : Fin (Nat.succ m + 1), ↑i := by
|
||||
rw [Fin.sum_univ_castSucc (n := m + 1)]
|
||||
rfl
|
||||
|
||||
OnlyTactics rw rfl
|
||||
|
||||
NewLemmas Fin.sum_univ_castSucc
|
||||
|
||||
Hint (m : ℕ) :
|
||||
∑ i : Fin (m + 1), (i : ℕ) + (m + 1) = ∑ i : Fin (Nat.succ m + 1), ↑i =>
|
||||
"
|
||||
Probier nochmals das gleiche, diesmal mit
|
||||
```
|
||||
rw [@Fin.sum_univ_castSucc _ _ (m + 1)]
|
||||
```
|
||||
anstatt
|
||||
```
|
||||
rw [Fin.sum_univ_castSucc (n := m + 1)]
|
||||
```
|
||||
"
|
||||
|
||||
Hint (m : ℕ) :
|
||||
∑ i : Fin m, (Fin.castSucc.toEmbedding i : ℕ) + ↑(Fin.last m) + (m + 1) =
|
||||
∑ i : Fin (Nat.succ m + 1), ↑i =>
|
||||
"Sackgasse!"
|
||||
|
||||
|
||||
Hint (m : ℕ) :
|
||||
∑ i : Fin (m + 1), (i : ℕ) + (m + 1) =
|
||||
∑ i : Fin (m + 1), ↑i + (m + 1) =>
|
||||
"Jetzt sind beide Seiten gleich und das Goal kann mit `rfl` geschlossen werden."
|
||||
Reference in New Issue
Block a user