Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 3de3cfb

Browse files
cipher1024digama0
authored andcommitted
feat(tactic/subtype_instance): generating subtype instances
1 parent b7b05fb commit 3de3cfb

File tree

9 files changed

+215
-12
lines changed

9 files changed

+215
-12
lines changed

data/list/basic.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,6 +3831,15 @@ theorem reverse_range' : ∀ s n : ℕ,
38313831
map prod.fst (enum l) = range l.length :=
38323832
by simp [enum, range_eq_range']
38333833

3834+
def map_head {α} (f : α → α) : list α → list α
3835+
| [] := []
3836+
| (x :: xs) := f x :: xs
3837+
3838+
def map_last {α} (f : α → α) : list α → list α
3839+
| [] := []
3840+
| [x] := [f x]
3841+
| (x :: xs) := x :: map_last xs
3842+
38343843
end list
38353844

38363845
theorem option.to_list_nodup {α} (o : option α) : o.to_list.nodup :=

data/string.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,7 @@ by refine_struct {
6767
decidable_eq := by apply_instance, .. };
6868
{ simp [-not_le], introv, apply_field }
6969

70-
end string
70+
def map_tokens (c : char) (f : list string → list string) : string → string :=
71+
intercalate (singleton c) ∘ f ∘ split (= c)
72+
73+
end string

field_theory/subfield.lean

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/-
2+
Copyright (c) 2018 Andreas Swerdlow. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Andreas Swerdlow
5+
-/
6+
7+
import ring_theory.subring
8+
9+
variables {F : Type*} [field F] (s : set F)
10+
11+
class is_subfield extends is_subring s :=
12+
(inv_mem : ∀ {x : F}, x ∈ s → x⁻¹ ∈ s)
13+
14+
open is_subfield
15+
16+
instance subset.field [is_subfield s] : field s :=
17+
by subtype_instance
18+
19+
instance subtype.field [is_subfield s] : field (subtype s) := subset.field s

group_theory/subgroup.lean

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,10 @@ theorem multiplicative.is_subgroup_iff
4848
λ h, by resetI; apply_instance⟩
4949

5050
instance subtype.group {s : set α} [is_subgroup s] : group s :=
51-
{ inv := λa, ⟨(a.1)⁻¹, is_subgroup.inv_mem a.2⟩,
52-
mul_left_inv := λa, subtype.eq $ mul_left_inv _,
53-
.. subtype.monoid }
51+
by subtype_instance
5452

5553
instance subtype.add_group {s : set β} [is_add_subgroup s] : add_group s :=
56-
{ neg := λa, ⟨-(a.1), is_add_subgroup.neg_mem a.2⟩,
57-
add_left_neg := λa, subtype.eq $ add_left_neg _,
58-
.. subtype.add_monoid }
54+
by subtype_instance
5955
attribute [to_additive subtype.add_group] subtype.group
6056

6157
theorem is_subgroup.of_div (s : set α)

group_theory/submonoid.lean

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Johannes Hölzl, Kenny Lau, Johan Commelin, Mario Carneiro
55
-/
66
import algebra.group_power
7+
import tactic.subtype_instance
78

89
variables {α : Type*} [monoid α] {s : set α}
910
variables {β : Type*} [add_monoid β] {t : set β}
@@ -81,15 +82,13 @@ lemma is_submonoid.list_prod_mem [is_submonoid s] : ∀{l : list α}, (∀x∈l,
8182
is_submonoid.mul_mem this.1 (is_submonoid.list_prod_mem this.2)
8283

8384
instance subtype.monoid {s : set α} [is_submonoid s] : monoid s :=
84-
{ mul := λ a b : s, ⟨a * b, is_submonoid.mul_mem a.2 b.2⟩,
85-
one := ⟨1, is_submonoid.one_mem s⟩,
86-
mul_assoc := λ a b c, subtype.eq $ mul_assoc _ _ _,
87-
one_mul := λ a, subtype.eq $ one_mul _,
88-
mul_one := λ a, subtype.eq $ mul_one _ }
85+
by subtype_instance
86+
8987
attribute [to_additive subtype.add_monoid._proof_1] subtype.monoid._proof_1
9088
attribute [to_additive subtype.add_monoid._proof_2] subtype.monoid._proof_2
9189
attribute [to_additive subtype.add_monoid._proof_3] subtype.monoid._proof_3
9290
attribute [to_additive subtype.add_monoid._proof_4] subtype.monoid._proof_4
91+
attribute [to_additive subtype.add_monoid._proof_5] subtype.monoid._proof_5
9392
attribute [to_additive subtype.add_monoid] subtype.monoid
9493

9594
namespace monoid

ring_theory/subring.lean

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/-
2+
Copyright (c) 2018 Johan Commelin. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johan Commelin
5+
-/
6+
7+
import group_theory.subgroup
8+
import data.polynomial
9+
import algebra.ring
10+
11+
local attribute [instance] classical.prop_decidable
12+
universes u v
13+
14+
open group
15+
16+
variables {R : Type u} [ring R]
17+
18+
/-- `S` is a subring: a set containing 1 and closed under multiplication, addition and and additive inverse. -/
19+
class is_subring (S : set R) extends is_add_subgroup S, is_submonoid S : Prop.
20+
21+
instance subset.ring {S : set R} [is_subring S] : ring S :=
22+
by subtype_instance
23+
24+
instance subtype.ring {S : set R} [is_subring S] : ring (subtype S) := subset.ring
25+
26+
namespace is_ring_hom
27+
28+
instance {S : set R} [is_subring S] : is_ring_hom (@subtype.val R S) :=
29+
by refine {..} ; intros ; refl
30+
31+
end is_ring_hom
32+
33+
variables {cR : Type u} [comm_ring cR]
34+
35+
instance subset.comm_ring {S : set cR} [is_subring S] : comm_ring S :=
36+
by subtype_instance
37+
38+
instance subtype.comm_ring {S : set cR} [is_subring S] : comm_ring (subtype S) := subset.comm_ring
39+
40+
instance subring.domain {D : Type*} [integral_domain D] (S : set D) [is_subring S] : integral_domain S :=
41+
by subtype_instance

tactic/algebra.lean

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/-
2+
Copyright (c) 2018 Simon Hudon. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Simon Hudon
5+
-/
6+
7+
import tactic.basic
8+
9+
open lean.parser
10+
11+
namespace tactic
12+
13+
@[user_attribute]
14+
meta def ancestor_attr : user_attribute unit (list name) :=
15+
{ name := `ancestor,
16+
descr := "ancestor of old structures",
17+
parser := many ident }
18+
19+
meta def get_ancestors (cl : name) : tactic (list name) :=
20+
(++) <$> (prod.fst <$> subobject_names cl <|> pure [])
21+
<*> (user_attribute.get_param ancestor_attr cl <|> pure [])
22+
23+
meta def find_ancestors : name → expr → tactic (list expr) | cl arg :=
24+
do cs ← get_ancestors cl,
25+
r ← cs.mmap $ λ c, list.ret <$> (mk_app c [arg] >>= mk_instance) <|> find_ancestors c arg,
26+
return r.join
27+
28+
end tactic
29+
30+
attribute [ancestor has_mul] semigroup
31+
attribute [ancestor semigroup has_one] monoid
32+
attribute [ancestor monoid has_inv] group
33+
attribute [ancestor group has_comm] comm_group
34+
attribute [ancestor has_add] add_semigroup
35+
attribute [ancestor add_semigroup has_zero] add_monoid
36+
attribute [ancestor add_monoid has_neg] add_group
37+
attribute [ancestor add_group has_add_comm] add_comm_group
38+
39+
attribute [ancestor ring has_inv zero_ne_one_class] division_ring
40+
attribute [ancestor division_ring comm_ring] field
41+
attribute [ancestor field] discrete_field
42+
43+
attribute [ancestor has_mul has_add] distrib
44+
attribute [ancestor has_mul has_zero] mul_zero_class
45+
attribute [ancestor has_zero has_one] zero_ne_one_class
46+
attribute [ancestor add_comm_monoid monoid distrib mul_zero_class] semiring
47+
attribute [ancestor semiring comm_monoid] comm_semiring
48+
attribute [ancestor add_comm_group monoid distrib] ring
49+
50+
attribute [ancestor ring comm_semigroup] comm_ring
51+
attribute [ancestor has_mul has_zero] no_zero_divisors
52+
attribute [ancestor comm_ring no_zero_divisors zero_ne_one_class] integral_domain

tactic/basic.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,4 +509,7 @@ do l ← local_context,
509509

510510
run_cmd add_interactive [`injections_and_clear]
511511

512+
meta def find_local (t : pexpr) : tactic expr :=
513+
do t' ← to_expr t,
514+
prod.snd <$> solve_aux t' assumption
512515
end tactic

tactic/subtype_instance.lean

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/-
2+
Copyright (c) 2018 Simon Hudon. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Simon Hudon
5+
6+
Provides a `subtype_instance` tactic which builds instances for algebraic substructures
7+
(sub-groups, sub-rings...).
8+
-/
9+
10+
import data.string
11+
import tactic.interactive tactic.algebra
12+
import data.subtype data.set.basic
13+
open tactic expr name list
14+
15+
namespace tactic
16+
17+
open tactic.interactive (get_current_field refine_struct)
18+
open lean lean.parser
19+
open interactive
20+
21+
/-- makes the substructure axiom name from field name, by postfacing with `_mem`-/
22+
def mk_mem_name (sub : name) : name → name
23+
| (mk_string n _) := mk_string (n ++ "_mem") sub
24+
| n := n
25+
26+
meta def derive_field_subtype : tactic unit :=
27+
do
28+
field ← get_current_field,
29+
b ← target >>= is_prop,
30+
if b then do
31+
`[simp [subtype.ext], dsimp],
32+
intros,
33+
applyc field; assumption
34+
else do
35+
s ← find_local ``(set _),
36+
`(set %%α) ← infer_type s,
37+
e ← mk_const field,
38+
expl_arity ← get_expl_arity $ e α,
39+
xs ← (iota expl_arity).mmap $ λ _, intro1,
40+
args ← xs.mmap $ λ x, mk_app `subtype.val [x],
41+
hyps ← xs.mmap $ λ x, mk_app `subtype.property [x],
42+
val ← mk_app field args,
43+
subname ← local_context >>= list.mfirst (λ h, do
44+
(expr.const n _, args) ← get_app_fn_args <$> infer_type h,
45+
is_def_eq s args.ilast reducible,
46+
return n),
47+
mem_field ← resolve_constant $ mk_mem_name subname field,
48+
val_mem ← mk_app mem_field hyps,
49+
`(coe_sort %%s) <- target >>= instantiate_mvars,
50+
tactic.refine ``(@subtype.mk _ %%s %%val %%val_mem)
51+
52+
namespace interactive
53+
54+
/-- builds instances for algebraic substructures
55+
56+
Example:
57+
```lean
58+
variables {α : Type*} [monoid α] {s : set α}
59+
60+
class is_submonoid (s : set α) : Prop :=
61+
(one_mem : (1:α) ∈ s)
62+
(mul_mem {a b} : a ∈ s → b ∈ s → a * b ∈ s)
63+
64+
instance subtype.monoid {s : set α} [is_submonoid s] : monoid s :=
65+
by subtype_instance
66+
````
67+
-/
68+
meta def subtype_instance :=
69+
do t ← target,
70+
let cl := t.get_app_fn.const_name,
71+
src ← find_ancestors cl t.app_arg,
72+
let inst := pexpr.mk_structure_instance
73+
{ struct := cl,
74+
field_values := [],
75+
field_names := [],
76+
sources := src.map to_pexpr },
77+
refine_struct inst ; derive_field_subtype
78+
79+
end interactive
80+
81+
end tactic

0 commit comments

Comments
 (0)