Skip to content

Commit 0519a9c

Browse files
authored
Merge pull request #98 from lakesare/lakesare_exercises_3
Exercises for Ch.Tactics
2 parents 478d0aa + dc3f42a commit 0519a9c

File tree

12 files changed

+945
-296
lines changed

12 files changed

+945
-296
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@ A PDF is [available here for download](../../releases/download/latest/Metaprogra
1515
8. [DSLs](md/main/08_dsls.md)
1616
9. [Tactics](md/main/09_tactics.md)
1717
10. [Cheat sheet](md/main/10_cheat-sheet.md)
18-
* Extra
1918
1. [Options](md/extra/01_options.md)
2019
2. [Attributes](md/extra/02_attributes.md)
21-
1. [Pretty Printing](md/extra/03_pretty-printing.md)
20+
3. [Pretty Printing](md/extra/03_pretty-printing.md)
2221
* Solutions to exercises
23-
1. ...
24-
2. ...
22+
1. Introduction
23+
2. Overview
2524
3. [Expressions](md/solutions/03_expressions.md)
2625
4. [`MetaM`](md/solutions/04_metam.md)
2726
5. [`Syntax`](md/solutions/05_syntax.md)
28-
6. ...
27+
6. Macros
2928
7. [Elaboration](md/solutions/07_elaboration.md)
29+
8. DSLs
30+
9. [Tactics](md/solutions/09_tactics.md)
3031

3132
Sources to extract material from:
3233
* [Material written by Ed](https://github.com/leanprover-community/mathlib4/blob/tutorial/docs/metaprogramming/02_metavariables.md)

lean/main/04_metam.lean

Lines changed: 69 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,47 +1214,47 @@ Notice that changing the type of the metavariable from `Nat` to, for example, `S
12141214
2. [**Metavariables**] What would `instantiateMVars (Lean.mkAppN (Expr.const 'Nat.add []) #[mkNatLit 1, mkNatLit 2])` output?
12151215
3. [**Metavariables**] Fill in the missing lines in the following code.
12161216
1217-
```
1218-
#eval show MetaM Unit from do
1219-
let oneExpr := Expr.app (Expr.const `Nat.succ []) (Expr.const ``Nat.zero [])
1220-
let twoExpr := Expr.app (Expr.const `Nat.succ []) oneExpr
1221-
1222-
-- Create `mvar1` with type `Nat`
1223-
-- let mvar1 ← ...
1224-
-- Create `mvar2` with type `Nat`
1225-
-- let mvar2 ← ...
1226-
-- Create `mvar3` with type `Nat`
1227-
-- let mvar3 ← ...
1228-
1229-
-- Assign `mvar1` to `2 + ?mvar2 + ?mvar3`
1230-
-- ...
1231-
1232-
-- Assign `mvar3` to `1`
1233-
-- ...
1234-
1235-
-- Instantiate `mvar1`, which should result in expression `2 + ?mvar2 + 1`
1236-
...
1237-
```
1217+
```lean
1218+
#eval show MetaM Unit from do
1219+
let oneExpr := Expr.app (Expr.const `Nat.succ []) (Expr.const ``Nat.zero [])
1220+
let twoExpr := Expr.app (Expr.const `Nat.succ []) oneExpr
1221+
1222+
-- Create `mvar1` with type `Nat`
1223+
-- let mvar1 ← ...
1224+
-- Create `mvar2` with type `Nat`
1225+
-- let mvar2 ← ...
1226+
-- Create `mvar3` with type `Nat`
1227+
-- let mvar3 ← ...
1228+
1229+
-- Assign `mvar1` to `2 + ?mvar2 + ?mvar3`
1230+
-- ...
1231+
1232+
-- Assign `mvar3` to `1`
1233+
-- ...
1234+
1235+
-- Instantiate `mvar1`, which should result in expression `2 + ?mvar2 + 1`
1236+
...
1237+
```
12381238
4. [**Metavariables**] Consider the theorem `red`, and tactic `explore` below.
1239-
a) What would be the `type` and `userName` of metavariable `mvarId`?
1240-
b) What would be the `type`s and `userName`s of all local declarations in this metavariable's local context?
1239+
**a)** What would be the `type` and `userName` of metavariable `mvarId`?
1240+
**b)** What would be the `type`s and `userName`s of all local declarations in this metavariable's local context?
12411241
Print them all out.
12421242
1243-
```
1244-
elab "explore" : tactic => do
1245-
let mvarId : MVarId ← Lean.Elab.Tactic.getMainGoal
1246-
let metavarDecl : MetavarDecl ← mvarId.getDecl
1243+
```lean
1244+
elab "explore" : tactic => do
1245+
let mvarId : MVarId ← Lean.Elab.Tactic.getMainGoal
1246+
let metavarDecl : MetavarDecl ← mvarId.getDecl
12471247
1248-
IO.println "Our metavariable"
1249-
-- ...
1248+
IO.println "Our metavariable"
1249+
-- ...
12501250
1251-
IO.println "All of its local declarations"
1252-
-- ...
1251+
IO.println "All of its local declarations"
1252+
-- ...
12531253
1254-
theorem red (hA : 1 = 1) (hB : 2 = 2) : 2 = 2 := by
1255-
explore
1256-
sorry
1257-
```
1254+
theorem red (hA : 1 = 1) (hB : 2 = 2) : 2 = 2 := by
1255+
explore
1256+
sorry
1257+
```
12581258
5. [**Metavariables**] Write a tactic `solve` that proves the theorem `red`.
12591259
6. [**Computation**] What is the normal form of the following expressions:
12601260
**a)** `fun x => x` of type `Bool → Bool`
@@ -1270,36 +1270,36 @@ Notice that changing the type of the metavariable from `Nat` to, for example, `S
12701270
**f)** `2 + ?a =?= 2 + 1`
12711271
9. [**Computation**] Write down what you expect the following code to output.
12721272
1273-
```
1274-
@[reducible] def reducibleDef : Nat := 1 -- same as `abbrev`
1275-
@[instance] def instanceDef : Nat := 2 -- same as `instance`
1276-
def defaultDef : Nat := 3
1277-
@[irreducible] def irreducibleDef : Nat := 4
1273+
```lean
1274+
@[reducible] def reducibleDef : Nat := 1 -- same as `abbrev`
1275+
@[instance] def instanceDef : Nat := 2 -- same as `instance`
1276+
def defaultDef : Nat := 3
1277+
@[irreducible] def irreducibleDef : Nat := 4
12781278
1279-
@[reducible] def sum := [reducibleDef, instanceDef, defaultDef, irreducibleDef]
1279+
@[reducible] def sum := [reducibleDef, instanceDef, defaultDef, irreducibleDef]
12801280
1281-
#eval show MetaM Unit from do
1282-
let constantExpr := Expr.const `sum []
1281+
#eval show MetaM Unit from do
1282+
let constantExpr := Expr.const `sum []
12831283
1284-
Meta.withTransparency Meta.TransparencyMode.reducible do
1285-
let reducedExpr ← Meta.reduce constantExpr
1286-
dbg_trace (← ppExpr reducedExpr) -- ...
1284+
Meta.withTransparency Meta.TransparencyMode.reducible do
1285+
let reducedExpr ← Meta.reduce constantExpr
1286+
dbg_trace (← ppExpr reducedExpr) -- ...
12871287
1288-
Meta.withTransparency Meta.TransparencyMode.instances do
1289-
let reducedExpr ← Meta.reduce constantExpr
1290-
dbg_trace (← ppExpr reducedExpr) -- ...
1288+
Meta.withTransparency Meta.TransparencyMode.instances do
1289+
let reducedExpr ← Meta.reduce constantExpr
1290+
dbg_trace (← ppExpr reducedExpr) -- ...
12911291
1292-
Meta.withTransparency Meta.TransparencyMode.default do
1293-
let reducedExpr ← Meta.reduce constantExpr
1294-
dbg_trace (← ppExpr reducedExpr) -- ...
1292+
Meta.withTransparency Meta.TransparencyMode.default do
1293+
let reducedExpr ← Meta.reduce constantExpr
1294+
dbg_trace (← ppExpr reducedExpr) -- ...
12951295
1296-
Meta.withTransparency Meta.TransparencyMode.all do
1297-
let reducedExpr ← Meta.reduce constantExpr
1298-
dbg_trace (← ppExpr reducedExpr) -- ...
1296+
Meta.withTransparency Meta.TransparencyMode.all do
1297+
let reducedExpr ← Meta.reduce constantExpr
1298+
dbg_trace (← ppExpr reducedExpr) -- ...
12991299
1300-
let reducedExpr ← Meta.reduce constantExpr
1301-
dbg_trace (← ppExpr reducedExpr) -- ...
1302-
```
1300+
let reducedExpr ← Meta.reduce constantExpr
1301+
dbg_trace (← ppExpr reducedExpr) -- ...
1302+
```
13031303
10. [**Constructing Expressions**] Create expression `fun x, 1 + x` in two ways:
13041304
**a)** not idiomatically, with loose bound variables
13051305
**b)** idiomatically.
@@ -1312,20 +1312,20 @@ def defaultDef : Nat := 3
13121312
13. [**Constructing Expressions**] Create expression `fun (f : Nat → Nat), ∀ (n : Nat), f n = f (n + 1)` idiomatically.
13131313
14. [**Constructing Expressions**] What would you expect the output of the following code to be?
13141314
1315-
```
1316-
#eval show Lean.Elab.Term.TermElabM _ from do
1317-
let stx : Syntax ← `(∀ (a : Prop) (b : Prop), a ∨ b → b → a ∧ a)
1318-
let expr ← Elab.Term.elabTermAndSynthesize stx none
1315+
```lean
1316+
#eval show Lean.Elab.Term.TermElabM _ from do
1317+
let stx : Syntax ← `(∀ (a : Prop) (b : Prop), a ∨ b → b → a ∧ a)
1318+
let expr ← Elab.Term.elabTermAndSynthesize stx none
13191319
1320-
let (_, _, conclusion) ← forallMetaTelescope expr
1321-
dbg_trace conclusion -- ...
1320+
let (_, _, conclusion) ← forallMetaTelescope expr
1321+
dbg_trace conclusion -- ...
13221322
1323-
let (_, _, conclusion) ← forallMetaBoundedTelescope expr 2
1324-
dbg_trace conclusion -- ...
1323+
let (_, _, conclusion) ← forallMetaBoundedTelescope expr 2
1324+
dbg_trace conclusion -- ...
13251325
1326-
let (_, _, conclusion) ← lambdaMetaTelescope expr
1327-
dbg_trace conclusion -- ...
1328-
```
1326+
let (_, _, conclusion) ← lambdaMetaTelescope expr
1327+
dbg_trace conclusion -- ...
1328+
```
13291329
15. [**Backtracking**] Check that the expressions `?a + Int` and `"hi" + ?b` are definitionally equal with `isDefEq` (make sure to use the proper types or `Option.none` for the types of your metavariables!).
13301330
Use `saveState` and `restoreState` to revert metavariable assignments.
13311331
-/

lean/main/05_syntax.lean

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -559,68 +559,68 @@ the bound variables, we refer the reader to the macro chapter.
559559
560560
1. Create an "urgent minus 💀" notation such that `5 * 8 💀 4` returns `20`, and `8 💀 6 💀 1` returns `3`.
561561
562-
**a)** Using `notation` command.
563-
**b)** Using `infix` command.
564-
**c)** Using `syntax` command.
562+
**a)** Using `notation` command.
563+
**b)** Using `infix` command.
564+
**c)** Using `syntax` command.
565565
566-
Hint: multiplication in Lean 4 is defined as `infixl:70 " * " => HMul.hMul`.
566+
Hint: multiplication in Lean 4 is defined as `infixl:70 " * " => HMul.hMul`.
567567
568568
2. Consider the following syntax categories: `term`, `command`, `tactic`; and 3 syntax rules given below. Make use of each of these newly defined syntaxes.
569569
570-
```
571-
syntax "good morning" : term
572-
syntax "hello" : command
573-
syntax "yellow" : tactic
574-
```
570+
```
571+
syntax "good morning" : term
572+
syntax "hello" : command
573+
syntax "yellow" : tactic
574+
```
575575
576576
3. Create a `syntax` rule that would accept the following commands:
577577
578-
- `red red red 4`
579-
- `blue 7`
580-
- `blue blue blue blue blue 18`
578+
- `red red red 4`
579+
- `blue 7`
580+
- `blue blue blue blue blue 18`
581581
582-
(So, either all `red`s followed by a number; or all `blue`s followed by a number; `red blue blue 5` - shouldn't work.)
582+
(So, either all `red`s followed by a number; or all `blue`s followed by a number; `red blue blue 5` - shouldn't work.)
583583
584-
Use the following code template:
584+
Use the following code template:
585585
586-
```
587-
syntax (name := colors) ...
588-
-- our "elaboration function" that infuses syntax with semantics
589-
@[command_elab colors] def elabColors : CommandElab := λ stx => Lean.logInfo "success!"
590-
```
586+
```lean
587+
syntax (name := colors) ...
588+
-- our "elaboration function" that infuses syntax with semantics
589+
@[command_elab colors] def elabColors : CommandElab := λ stx => Lean.logInfo "success!"
590+
```
591591
592592
4. Mathlib has a `#help option` command that displays all options available in the current environment, and their descriptions. `#help option pp.r` will display all options starting with a "pp.r" substring.
593593
594-
Create a `syntax` rule that would accept the following commands:
594+
Create a `syntax` rule that would accept the following commands:
595595
596-
- `#better_help option`
597-
- `#better_help option pp.r`
598-
- `#better_help option some.other.name`
596+
- `#better_help option`
597+
- `#better_help option pp.r`
598+
- `#better_help option some.other.name`
599599
600-
Use the following template:
600+
Use the following template:
601601
602-
```
603-
syntax (name := help) ...
604-
-- our "elaboration function" that infuses syntax with semantics
605-
@[command_elab help] def elabHelp : CommandElab := λ stx => Lean.logInfo "success!"
606-
```
602+
```lean
603+
syntax (name := help) ...
604+
-- our "elaboration function" that infuses syntax with semantics
605+
@[command_elab help] def elabHelp : CommandElab := λ stx => Lean.logInfo "success!"
606+
```
607607
608608
5. Mathlib has a ∑ operator. Create a `syntax` rule that would accept the following terms:
609609
610-
- `∑ x in { 1, 2, 3 }, x^2`
611-
- `∑ x in { "apple", "banana", "cherry" }, x.length`
610+
- `∑ x in { 1, 2, 3 }, x^2`
611+
- `∑ x in { "apple", "banana", "cherry" }, x.length`
612612
613-
Use the following template:
613+
Use the following template:
614614
615-
```
616-
import Std.Classes.SetNotation
617-
import Std.Util.ExtendedBinder
618-
syntax (name := bigsumin) ...
619-
-- our "elaboration function" that infuses syntax with semantics
620-
@[term_elab bigsumin] def elabSum : TermElab := λ stx tp => return mkNatLit 666
621-
```
615+
```lean
616+
import Std.Classes.SetNotation
617+
import Std.Util.ExtendedBinder
618+
syntax (name := bigsumin) ...
619+
-- our "elaboration function" that infuses syntax with semantics
620+
@[term_elab bigsumin] def elabSum : TermElab := λ stx tp => return mkNatLit 666
621+
```
622622
623-
Hint: use the `Std.ExtendedBinder.extBinder` parser.
624-
Hint: you need Std4 installed in your Lean project for these imports to work.
623+
Hint: use the `Std.ExtendedBinder.extBinder` parser.
624+
Hint: you need Std4 installed in your Lean project for these imports to work.
625625
626626
-/

lean/main/07_elaboration.lean

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -348,52 +348,52 @@ elab "⟨⟨" args:term,* "⟩⟩" : term <= t => do
348348
349349
1. Consider the following code. Rewrite `syntax` + `@[term_elab hi]... : TermElab` combination using just `elab`.
350350
351-
```
352-
syntax (name := hi) term " ♥ " " ♥ "? " ♥ "? : term
353-
354-
@[term_elab hi]
355-
def heartElab : TermElab := fun stx tp =>
356-
match stx with
357-
| `($l:term ♥) => do
358-
let nExpr ← elabTermEnsuringType l (mkConst `Nat)
359-
return Expr.app (Expr.app (Expr.const `Nat.add []) nExpr) (mkNatLit 1)
360-
| `($l:term ♥♥) => do
361-
let nExpr ← elabTermEnsuringType l (mkConst `Nat)
362-
return Expr.app (Expr.app (Expr.const `Nat.add []) nExpr) (mkNatLit 2)
363-
| `($l:term ♥♥♥) => do
364-
let nExpr ← elabTermEnsuringType l (mkConst `Nat)
365-
return Expr.app (Expr.app (Expr.const `Nat.add []) nExpr) (mkNatLit 3)
366-
| _ =>
367-
throwUnsupportedSyntax
368-
```
351+
```lean
352+
syntax (name := hi) term " ♥ " " ♥ "? " ♥ "? : term
353+
354+
@[term_elab hi]
355+
def heartElab : TermElab := fun stx tp =>
356+
match stx with
357+
| `($l:term ♥) => do
358+
let nExpr ← elabTermEnsuringType l (mkConst `Nat)
359+
return Expr.app (Expr.app (Expr.const `Nat.add []) nExpr) (mkNatLit 1)
360+
| `($l:term ♥♥) => do
361+
let nExpr ← elabTermEnsuringType l (mkConst `Nat)
362+
return Expr.app (Expr.app (Expr.const `Nat.add []) nExpr) (mkNatLit 2)
363+
| `($l:term ♥♥♥) => do
364+
let nExpr ← elabTermEnsuringType l (mkConst `Nat)
365+
return Expr.app (Expr.app (Expr.const `Nat.add []) nExpr) (mkNatLit 3)
366+
| _ =>
367+
throwUnsupportedSyntax
368+
```
369369
370370
2. Here is some syntax taken from a real mathlib command `alias`.
371371
372-
```
373-
syntax (name := our_alias) (docComment)? "our_alias " ident " ← " ident* : command
374-
```
372+
```
373+
syntax (name := our_alias) (docComment)? "our_alias " ident " ← " ident* : command
374+
```
375375
376-
We want `alias hi ← hello yes` to print out the identifiers after `←` - that is, "hello" and "yes".
376+
We want `alias hi ← hello yes` to print out the identifiers after `←` - that is, "hello" and "yes".
377377
378-
Please add these semantics:
378+
Please add these semantics:
379379
380-
**a)** using `syntax` + `@[command_elab alias] def elabOurAlias : CommandElab`.
381-
**b)** using `syntax` + `elab_rules`.
382-
**c)** using `elab`.
380+
**a)** using `syntax` + `@[command_elab alias] def elabOurAlias : CommandElab`.
381+
**b)** using `syntax` + `elab_rules`.
382+
**c)** using `elab`.
383383
384384
3. Here is some syntax taken from a real mathlib tactic `nth_rewrite`.
385385
386-
```
387-
open Parser.Tactic
388-
syntax (name := nthRewriteSeq) "nth_rewrite " (config)? num rwRuleSeq (ppSpace location)? : tactic
389-
```
386+
```lean
387+
open Parser.Tactic
388+
syntax (name := nthRewriteSeq) "nth_rewrite " (config)? num rwRuleSeq (ppSpace location)? : tactic
389+
```
390390
391-
We want `nth_rewrite 5 [←add_zero a] at h` to print out `"rewrite location!"` if the user provided location, and `"rewrite target!"` if the user didn't provide location.
391+
We want `nth_rewrite 5 [←add_zero a] at h` to print out `"rewrite location!"` if the user provided location, and `"rewrite target!"` if the user didn't provide location.
392392
393-
Please add these semantics:
393+
Please add these semantics:
394394
395-
**a)** using `syntax` + `@[tactic nthRewrite] def elabNthRewrite : Lean.Elab.Tactic.Tactic`.
396-
**b)** using `syntax` + `elab_rules`.
397-
**c)** using `elab`.
395+
**a)** using `syntax` + `@[tactic nthRewrite] def elabNthRewrite : Lean.Elab.Tactic.Tactic`.
396+
**b)** using `syntax` + `elab_rules`.
397+
**c)** using `elab`.
398398
399399
-/

0 commit comments

Comments
 (0)