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

Commit bde2132

Browse files
cipher1024digama0
authored andcommitted
feat(category/traversable): derive traversable instances
Authors: Simon Hudon, Mario Carneiro
1 parent d288f07 commit bde2132

File tree

13 files changed

+898
-506
lines changed

13 files changed

+898
-506
lines changed

category/applicative.lean

Lines changed: 71 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,41 @@ section lemmas
1414

1515
open function
1616

17-
variables {f : Type u → Type v}
18-
variables [applicative f] [is_lawful_applicative f]
17+
variables {F : Type u → Type v}
18+
variables [applicative F] [is_lawful_applicative F]
1919
variables {α β γ σ : Type u}
2020

2121
attribute [functor_norm] seq_assoc pure_seq_eq_map map_pure seq_map_assoc map_seq
2222

23-
lemma applicative.map_seq_map (g : α → β → γ) (h : σ → β) (x : f α) (y : f σ) :
24-
(g <$> x) <*> (h <$> y) = (flip (∘) hg) <$> x <*> y :=
23+
lemma applicative.map_seq_map (f : α → β → γ) (g : σ → β) (x : F α) (y : F σ) :
24+
(f <$> x) <*> (g <$> y) = (flip (∘) gf) <$> x <*> y :=
2525
by simp [flip] with functor_norm
2626

27-
lemma applicative.pure_seq_eq_map' (g : α → β) :
28-
(<*>) (pure g : f (α → β)) = (<$>) g :=
29-
by funext; simp with functor_norm
27+
lemma applicative.pure_seq_eq_map' (f : α → β) :
28+
(<*>) (pure f : F (α → β)) = (<$>) f :=
29+
by ext; simp with functor_norm
30+
31+
theorem applicative.ext {F} : ∀ {A1 : applicative F} {A2 : applicative F}
32+
[@is_lawful_applicative F A1] [@is_lawful_applicative F A2]
33+
(H1 : ∀ {α : Type u} (x : α),
34+
@has_pure.pure _ A1.to_has_pure _ x = @has_pure.pure _ A2.to_has_pure _ x)
35+
(H2 : ∀ {α β : Type u} (f : F (α → β)) (x : F α),
36+
@has_seq.seq _ A1.to_has_seq _ _ f x = @has_seq.seq _ A2.to_has_seq _ _ f x),
37+
A1 = A2
38+
| {to_functor := F1, seq := s1, pure := p1, seq_left := sl1, seq_right := sr1}
39+
{to_functor := F2, seq := s2, pure := p2, seq_left := sl2, seq_right := sr2} L1 L2 H1 H2 :=
40+
begin
41+
have : @p1 = @p2, {funext α x, apply H1}, subst this,
42+
have : @s1 = @s2, {funext α β f x, apply H2}, subst this,
43+
cases L1, cases L2,
44+
have : F1 = F2,
45+
{ resetI, apply functor.ext, intros,
46+
exact (L1_pure_seq_eq_map _ _).symm.trans (L2_pure_seq_eq_map _ _) },
47+
subst this,
48+
congr; funext α β x y,
49+
{ exact (L1_seq_left_eq _ _).trans (L2_seq_left_eq _ _).symm },
50+
{ exact (L1_seq_right_eq _ _).trans (L2_seq_right_eq _ _).symm }
51+
end
3052

3153
end lemmas
3254

@@ -35,63 +57,64 @@ namespace comp
3557
open function (hiding comp)
3658
open functor
3759

38-
variables {f : Type u → Type w} {g : Type v → Type u}
60+
variables {F : Type u → Type w} {G : Type v → Type u}
3961

40-
variables [applicative f] [applicative g]
62+
variables [applicative F] [applicative G]
4163

42-
protected def seq {α β : Type v} : comp f g (α → β) → comp f g α → comp f g β
43-
| ⟨h⟩ ⟨x⟩ := ⟨has_seq.seq <$> h <*> x
64+
protected def seq {α β : Type v} : comp F G (α → β) → comp F G α → comp F G β
65+
| (comp.mk f) (comp.mk x) := comp.mk $ (<*>) <$> f <*> x
4466

45-
instance : has_pure (comp f g) :=
46-
⟨λ _ x, pure $ pure x
67+
instance : has_pure (comp F G) :=
68+
⟨λ _ x, comp.mk $ pure $ pure x⟩
4769

48-
instance : has_seq (comp f g) :=
70+
instance : has_seq (comp F G) :=
4971
⟨λ _ _ f x, comp.seq f x⟩
5072

51-
@[simp]
52-
protected lemma run_pure {α : Type v} :
53-
∀ x : α, (pure x : comp f g α).run = pure (pure x)
73+
@[simp] protected lemma run_pure {α : Type v} :
74+
∀ x : α, (pure x : comp F G α).run = pure (pure x)
5475
| _ := rfl
5576

56-
@[simp]
57-
protected lemma run_seq {α β : Type v} :
58-
∀ (h : comp f g (α → β)) (x : comp f g α),
59-
(h <*> x).run = (<*>) <$> h.run <*> x.run
60-
| ⟨_⟩ ⟨_⟩ := rfl
77+
@[simp] protected lemma run_seq {α β : Type v} (f : comp F G (α → β)) (x : comp F G α) :
78+
(f <*> x).run = (<*>) <$> f.run <*> x.run := rfl
6179

62-
variables [is_lawful_applicative f] [is_lawful_applicative g]
80+
instance : applicative (comp F G) :=
81+
{ map := @comp.map F G _ _,
82+
seq := @comp.seq F G _ _,
83+
..comp.has_pure }
84+
85+
variables [is_lawful_applicative F] [is_lawful_applicative G]
6386
variables {α β γ : Type v}
6487

65-
lemma map_pure (h : α → β) (x : α) : (h <$> pure x : comp f g β) = pure (h x) :=
66-
by ext; simp
88+
lemma map_pure (f : α → β) (x : α) : (f <$> pure x : comp F G β) = pure (f x) :=
89+
comp.ext $ by simp
6790

68-
lemma seq_pure (h : comp f g (α → β)) (x : α) :
69-
h <*> pure x = (λ g : α → β, g x) <$> h :=
70-
by ext; simp [(∘)] with functor_norm
91+
lemma seq_pure (f : comp F G (α → β)) (x : α) :
92+
f <*> pure x = (λ g : α → β, g x) <$> f :=
93+
comp.ext $ by simp [(∘)] with functor_norm
7194

72-
lemma seq_assoc (x : comp f g α) (h₀ : comp f g (α → β)) (h₁ : comp f g (β → γ)) :
73-
h₁ <*> (h₀ <*> x) = (@function.comp α β γ <$> h₁) <*> h₀ <*> x :=
74-
by ext; simp [(∘)] with functor_norm
95+
lemma seq_assoc (x : comp F G α) (f : comp F G (α → β)) (g : comp F G (β → γ)) :
96+
g <*> (f <*> x) = (@function.comp α β γ <$> g) <*> f <*> x :=
97+
comp.ext $ by simp [(∘)] with functor_norm
7598

76-
lemma pure_seq_eq_map (h : α → β) (x : comp f g α) :
77-
pure h <*> x = h <$> x :=
78-
by ext; simp [applicative.pure_seq_eq_map'] with functor_norm
99+
lemma pure_seq_eq_map (f : α → β) (x : comp F G α) :
100+
pure f <*> x = f <$> x :=
101+
comp.ext $ by simp [applicative.pure_seq_eq_map'] with functor_norm
79102

80-
instance {f : Type u → Type w} {g : Type v → Type u}
81-
[applicative f] [applicative g] :
82-
applicative (comp f g) :=
83-
{ map := @comp.map f g _ _,
84-
seq := @comp.seq f g _ _,
85-
..comp.has_pure }
103+
instance : is_lawful_applicative (comp F G) :=
104+
{ pure_seq_eq_map := @comp.pure_seq_eq_map F G _ _ _ _,
105+
map_pure := @comp.map_pure F G _ _ _ _,
106+
seq_pure := @comp.seq_pure F G _ _ _ _,
107+
seq_assoc := @comp.seq_assoc F G _ _ _ _ }
86108

87-
instance {f : Type u → Type w} {g : Type v → Type u}
88-
[applicative f] [applicative g]
89-
[is_lawful_applicative f] [is_lawful_applicative g] :
90-
is_lawful_applicative (comp f g) :=
91-
{ pure_seq_eq_map := @comp.pure_seq_eq_map f g _ _ _ _,
92-
map_pure := @comp.map_pure f g _ _ _ _,
93-
seq_pure := @comp.seq_pure f g _ _ _ _,
94-
seq_assoc := @comp.seq_assoc f g _ _ _ _ }
109+
theorem applicative_id_comp {F} [AF : applicative F] [LF : is_lawful_applicative F] :
110+
@comp.applicative id F _ _ = AF :=
111+
@applicative.ext F _ _ (@comp.is_lawful_applicative id F _ _ _ _) _
112+
(λ α x, rfl) (λ α β f x, rfl)
113+
114+
theorem applicative_comp_id {F} [AF : applicative F] [LF : is_lawful_applicative F] :
115+
@comp.applicative F id _ _ = AF :=
116+
@applicative.ext F _ _ (@comp.is_lawful_applicative F id _ _ _ _) _
117+
(λ α x, rfl) (λ α β f x, show id <$> f <*> x = f <*> x, by rw id_map)
95118

96119
end comp
97120
open functor

category/basic.lean

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,49 +25,49 @@ run_cmd mk_simp_attr `functor_norm
2525
end functor
2626

2727
section applicative
28-
variables {f : Type u → Type v} [applicative f]
28+
variables {F : Type u → Type v} [applicative F]
2929

3030
def mzip_with
3131
{α₁ α₂ φ : Type u}
32-
(g : α₁ → α₂ → f φ) :
33-
Π (ma₁ : list α₁) (ma₂: list α₂), f (list φ)
34-
| (x :: xs) (y :: ys) := (::) <$> g x y <*> mzip_with xs ys
32+
(f : α₁ → α₂ → F φ) :
33+
Π (ma₁ : list α₁) (ma₂: list α₂), F (list φ)
34+
| (x :: xs) (y :: ys) := (::) <$> f x y <*> mzip_with xs ys
3535
| _ _ := pure []
3636

37-
def mzip_with' (g : α → β → f γ) : list α → list β → f punit
38-
| (x :: xs) (y :: ys) := g x y *> mzip_with' xs ys
37+
def mzip_with' (f : α → β → F γ) : list α → list β → F punit
38+
| (x :: xs) (y :: ys) := f x y *> mzip_with' xs ys
3939
| [] _ := pure punit.star
4040
| _ [] := pure punit.star
4141

42-
protected def option.traverse {α β : Type*} (g : α → f β) : option α → f (option β)
42+
protected def option.traverse {α β : Type*} (f : α → F β) : option α → F (option β)
4343
| none := pure none
44-
| (some x) := some <$> g x
44+
| (some x) := some <$> f x
4545

46-
protected def list.traverse {α β : Type*} (g : α → f β) : list α → f (list β)
46+
protected def list.traverse {α β : Type*} (f : α → F β) : list α → F (list β)
4747
| [] := pure []
48-
| (x :: xs) := list.cons <$> g x <*> list.traverse xs
48+
| (x :: xs) := list.cons <$> f x <*> list.traverse xs
4949

50-
variables [is_lawful_applicative f]
50+
variables [is_lawful_applicative F]
5151

5252
attribute [functor_norm] seq_assoc pure_seq_eq_map
5353

54-
@[simp] theorem pure_id'_seq (x : f α) : pure (λx, x) <*> x = x :=
54+
@[simp] theorem pure_id'_seq (x : F α) : pure (λx, x) <*> x = x :=
5555
pure_id_seq x
5656

57-
variables [is_lawful_applicative f]
57+
variables [is_lawful_applicative F]
5858

5959
attribute [functor_norm] seq_assoc pure_seq_eq_map
6060

61-
@[functor_norm] theorem seq_map_assoc (x : f (α → β)) (g : γ → α) (y : f γ) :
62-
(x <*> (g <$> y)) = (λ(m:α→β), m ∘ g) <$> x <*> y :=
61+
@[functor_norm] theorem seq_map_assoc (x : F (α → β)) (f : γ → α) (y : F γ) :
62+
(x <*> (f <$> y)) = (λ(m:α→β), m ∘ f) <$> x <*> y :=
6363
begin
6464
simp [(pure_seq_eq_map _ _).symm],
6565
simp [seq_assoc, (comp_map _ _ _).symm, (∘)],
6666
simp [pure_seq_eq_map]
6767
end
6868

69-
@[functor_norm] theorem map_seq (g : β → γ) (x : f (α → β)) (y : f α) :
70-
(g <$> (x <*> y)) = ((∘) g) <$> x <*> y :=
69+
@[functor_norm] theorem map_seq (f : β → γ) (x : F (α → β)) (y : F α) :
70+
(f <$> (x <*> y)) = ((∘) f) <$> x <*> y :=
7171
by simp [(pure_seq_eq_map _ _).symm]; simp [seq_assoc]
7272

7373
end applicative
@@ -76,6 +76,15 @@ end applicative
7676
section monad
7777
variables {m : Type u → Type v} [monad m] [is_lawful_monad m]
7878

79+
open list
80+
81+
def list.mpartition {f : TypeType} [monad f] {α : Type} (p : α → f bool) :
82+
list α → f (list α × list α)
83+
| [] := pure ([],[])
84+
| (x :: xs) :=
85+
mcond (p x) (prod.map (cons x) id <$> list.mpartition xs)
86+
(prod.map id (cons x) <$> list.mpartition xs)
87+
7988
lemma map_bind (x : m α) {g : α → m β} {f : β → γ} : f <$> (x >>= g) = (x >>= λa, f <$> g a) :=
8089
by rw [← bind_pure_comp_eq_map,bind_assoc]; simp [bind_pure_comp_eq_map]
8190

@@ -89,17 +98,17 @@ lemma seq_eq_bind_map {x : m α} {f : m (α → β)} : f <*> x = (f >>= (<$> x))
8998
end monad
9099

91100
section alternative
92-
variables {f : TypeType v} [alternative f]
101+
variables {F : TypeType v} [alternative F]
93102

94-
def succeeds {α} (x : f α) : f bool := (x $> tt) <|> pure ff
103+
def succeeds {α} (x : F α) : F bool := (x $> tt) <|> pure ff
95104

96-
def mtry {α} (x : f α) : f unit := (x $> ()) <|> pure ()
105+
def mtry {α} (x : F α) : F unit := (x $> ()) <|> pure ()
97106

98107
@[simp] theorem guard_true {h : decidable true} :
99-
@guard f _ true h = pure () := by simp [guard]
108+
@guard F _ true h = pure () := by simp [guard]
100109

101110
@[simp] theorem guard_false {h : decidable false} :
102-
@guard f _ false h = failure := by simp [guard]
111+
@guard F _ false h = failure := by simp [guard]
103112

104113
end alternative
105114

category/functor.lean

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ Author: Simon Hudon
55
66
Standard identity and composition functors
77
-/
8-
import tactic.ext
9-
import category.basic
8+
import tactic.ext tactic.cache category.basic
109

1110
universe variables u v w
1211

@@ -23,6 +22,20 @@ lemma functor.map_comp_map (f : α → β) (g : β → γ) :
2322
((<$>) g ∘ (<$>) f : F α → F γ) = (<$>) (g ∘ f) :=
2423
by apply funext; intro; rw comp_map
2524

25+
theorem functor.ext {F} : ∀ {F1 : functor F} {F2 : functor F}
26+
[@is_lawful_functor F F1] [@is_lawful_functor F F2]
27+
(H : ∀ α β (f : α → β) (x : F α),
28+
@functor.map _ F1 _ _ f x = @functor.map _ F2 _ _ f x),
29+
F1 = F2
30+
| ⟨m, mc⟩ ⟨m', mc'⟩ H1 H2 H :=
31+
begin
32+
cases show @m = @m', by funext α β f x; apply H,
33+
congr, funext α β,
34+
have E1 := @map_const_eq _ ⟨@m, @mc⟩ H1,
35+
have E2 := @map_const_eq _ ⟨@m, @mc'⟩ H2,
36+
exact E1.trans E2.symm
37+
end
38+
2639
end functor
2740

2841
def id.mk {α : Sort u} : α → id α := id
@@ -31,61 +44,59 @@ namespace functor
3144

3245
/-- `functor.comp` is a wrapper around `function.comp` for types.
3346
It prevents Lean's type class resolution mechanism from trying
34-
a `functor (comp f id)` when `functor f` would do. -/
35-
structure comp (f : Type u → Type w) (g : Type v → Type u) (α : Type v) : Type w :=
36-
(run : f $ g α)
47+
a `functor (comp F id)` when `functor F` would do. -/
48+
def comp (F : Type u → Type w) (G : Type v → Type u) (α : Type v) : Type w :=
49+
F $ G α
50+
51+
@[pattern] def comp.mk {F : Type u → Type w} {G : Type v → Type u} {α : Type v}
52+
(x : F (G α)) : comp F G α := x
3753

38-
@[extensionality]
39-
protected lemma comp.ext {f : Type u → Type w} {g : Type v → Type u} {α : Type v} :
40-
∀ {x y : comp f g α}, x.run = y.run → x = y
41-
| ⟨x⟩ ⟨._⟩ rfl := rfl
54+
def comp.run {F : Type u → Type w} {G : Type v → Type u} {α : Type v}
55+
(x : comp F G α) : F (G α) := x
4256

4357
namespace comp
4458

45-
variables {f : Type u → Type w} {g : Type v → Type u}
59+
variables {F : Type u → Type w} {G : Type v → Type u}
60+
61+
protected lemma ext
62+
{α} {x y : comp F G α} : x.run = y.run → x = y := id
4663

47-
variables [functor f] [functor g]
64+
variables [functor F] [functor G]
4865

49-
protected def map {α β : Type v} (h : α → β) : comp f g α → comp f g β
50-
| ⟨x⟩ := ⟨(<$>) h <$> x
66+
protected def map {α β : Type v} (h : α → β) : comp F G α → comp F G β
67+
| (comp.mk x) := comp.mk ((<$>) h <$> x)
5168

52-
variables [is_lawful_functor f] [is_lawful_functor g]
69+
instance : functor (comp F G) := { map := @comp.map F G _ _ }
70+
71+
@[functor_norm] lemma map_mk {α β} (h : α → β) (x : F (G α)) :
72+
h <$> comp.mk x = comp.mk ((<$>) h <$> x) := rfl
73+
74+
variables [is_lawful_functor F] [is_lawful_functor G]
5375
variables {α β γ : Type v}
5476

55-
protected lemma id_map : ∀ (x : comp f g α), comp.map id x = x
56-
| ⟨x⟩ :=
57-
by simp [comp.map,functor.map_id]
77+
protected lemma id_map : ∀ (x : comp F G α), comp.map id x = x
78+
| (comp.mk x) := by simp [comp.map, functor.map_id]
5879

59-
protected lemma comp_map (g_1 : α → β) (h : β → γ) : ∀ (x : comp f g α),
60-
comp.map (h ∘ g_1) x = comp.map h (comp.map g_1 x)
61-
| ⟨x⟩ :=
62-
by simp [comp.map,functor.map_comp_map g_1 h] with functor_norm
80+
protected lemma comp_map (g' : α → β) (h : β → γ) : ∀ (x : comp F G α),
81+
comp.map (h ∘ g') x = comp.map h (comp.map g' x)
82+
| (comp.mk x) := by simp [comp.map, functor.map_comp_map g' h] with functor_norm
6383

64-
instance {f : Type u → Type w} {g : Type v → Type u}
65-
[functor f] [functor g] :
66-
functor (comp f g) :=
67-
{ map := @comp.map f g _ _ }
84+
@[simp] protected lemma run_map (h : α → β) (x : comp F G α) :
85+
(h <$> x).run = (<$>) h <$> x.run := rfl
6886

69-
@[simp]
70-
protected lemma run_map {α β : Type v} (h : α → β) :
71-
∀ x : comp f g α, (h <$> x).run = (<$>) h <$> x.run
72-
| ⟨_⟩ := rfl
87+
instance : is_lawful_functor (comp F G) :=
88+
{ id_map := @comp.id_map F G _ _ _ _,
89+
comp_map := @comp.comp_map F G _ _ _ _ }
7390

74-
instance {f : Type u → Type w} {g : Type v → Type u}
75-
[functor f] [functor g]
76-
[is_lawful_functor f] [is_lawful_functor g] :
77-
is_lawful_functor (comp f g) :=
78-
{ id_map := @comp.id_map f g _ _ _ _,
79-
comp_map := @comp.comp_map f g _ _ _ _ }
91+
theorem functor_comp_id {F} [AF : functor F] [is_lawful_functor F] :
92+
@comp.functor F id _ _ = AF :=
93+
@functor.ext F _ AF (@comp.is_lawful_functor F id _ _ _ _) _ (λ α β f x, rfl)
8094

81-
end comp
95+
theorem functor_id_comp {F} [AF : functor F] [is_lawful_functor F] :
96+
@comp.functor id F _ _ = AF :=
97+
@functor.ext F _ AF (@comp.is_lawful_functor id F _ _ _ _) _ (λ α β f x, rfl)
8298

83-
@[functor_norm]
84-
lemma comp.map_mk {α β : Type w}
85-
{f : Type u → Type v} {g : Type w → Type u}
86-
[functor f] [functor g]
87-
(h : α → β) (x : f (g α)) :
88-
h <$> comp.mk x = comp.mk ((<$>) h <$> x) := rfl
99+
end comp
89100

90101
end functor
91102

0 commit comments

Comments
 (0)