move lemma-\notin-lookupM-assoc to Precond
[~helmut/bidiragda.git] / Bidir.agda
1 open import Relation.Binary.Core using (Decidable ; _≡_)
2
3 module Bidir (Carrier : Set) (deq : Decidable {A = Carrier} _≡_) where
4
5 open import Data.Nat using (ℕ)
6 open import Data.Fin using (Fin)
7 open import Data.Maybe using (Maybe ; nothing ; just ; maybe′)
8 open import Data.List using (List)
9 open import Data.List.All using (All)
10 open import Data.Vec using (Vec ; [] ; _∷_ ; toList ; map ; tabulate) renaming (lookup to lookupVec)
11 open import Data.Vec.Properties using (tabulate-∘ ; lookup∘tabulate ; map-cong ; map-∘)
12 open import Data.Product using (∃ ; _×_ ; _,_ ; proj₁ ; proj₂)
13 open import Function using (id ; _∘_ ; flip)
14 open import Relation.Binary.Core using (refl)
15 open import Relation.Binary.PropositionalEquality using (cong ; sym ; inspect ; [_] ; trans ; cong₂)
16 open Relation.Binary.PropositionalEquality.≡-Reasoning using (begin_ ; _≡⟨_⟩_ ; _∎)
17
18 import FreeTheorems
19 open FreeTheorems.VecVec using (get-type ; free-theorem)
20 open import FinMap
21 import CheckInsert
22 open CheckInsert Carrier deq
23 open import BFF using (_>>=_ ; fmap)
24 open BFF.VecBFF Carrier deq using (assoc ; enumerate ; denumerate ; bff)
25
26 lemma-1 : {m n : ℕ} → (f : Fin n → Carrier) → (is : Vec (Fin n) m) → assoc is (map f is) ≡ just (restrict f (toList is))
27 lemma-1 f []        = refl
28 lemma-1 f (i ∷ is′) = begin
29   assoc is′ (map f is′) >>= checkInsert i (f i)
30     ≡⟨ cong (λ m → m >>= checkInsert i (f i)) (lemma-1 f is′) ⟩
31   checkInsert i (f i) (restrict f (toList is′))
32     ≡⟨ lemma-checkInsert-restrict f i (toList is′) ⟩
33   just (restrict f (toList (i ∷ is′))) ∎
34
35 lemma-lookupM-assoc : {m n : ℕ} → (i : Fin n) → (is : Vec (Fin n) m) → (x : Carrier) → (xs : Vec Carrier m) → (h : FinMapMaybe n Carrier) → assoc (i ∷ is) (x ∷ xs) ≡ just h → lookupM i h ≡ just x
36 lemma-lookupM-assoc i is x xs h    p with assoc is xs
37 lemma-lookupM-assoc i is x xs h    () | nothing
38 lemma-lookupM-assoc i is x xs h    p | just h' with checkInsert i x h' | insertionresult i x h'
39 lemma-lookupM-assoc i is x xs .h refl | just h | ._ | same pl = pl
40 lemma-lookupM-assoc i is x xs ._ refl | just h' | ._ | new _ = lemma-lookupM-insert i x h'
41 lemma-lookupM-assoc i is x xs h () | just h' | ._ | wrong _ _ _
42
43 _in-domain-of_ : {n : ℕ} {A : Set} → (is : List (Fin n)) → (FinMapMaybe n A) → Set
44 _in-domain-of_ is h = All (λ i → ∃ λ x → lookupM i h ≡ just x) is
45
46 lemma-assoc-domain : {m n : ℕ} → (is : Vec (Fin n) m) → (xs : Vec Carrier m) → (h : FinMapMaybe n Carrier) → assoc is xs ≡ just h → (toList is) in-domain-of h
47 lemma-assoc-domain []         []         h ph = Data.List.All.[]
48 lemma-assoc-domain (i' ∷ is') (x' ∷ xs') h ph with assoc is' xs' | inspect (assoc is') xs'
49 lemma-assoc-domain (i' ∷ is') (x' ∷ xs') h () | nothing | [ ph' ]
50 lemma-assoc-domain (i' ∷ is') (x' ∷ xs') h ph | just h' | [ ph' ] with checkInsert i' x' h' | inspect (checkInsert i' x') h' | insertionresult i' x' h'
51 lemma-assoc-domain (i' ∷ is') (x' ∷ xs') .h refl | just h | [ ph' ] | ._ | _ | same pl = All._∷_ (x' , pl) (lemma-assoc-domain is' xs' h ph')
52 lemma-assoc-domain (i' ∷ is') (x' ∷ xs') ._ refl | just h' | [ ph' ] | ._ | [ cI≡ ] | new _ = All._∷_
53   (x' , lemma-lookupM-insert i' x' h')
54   (Data.List.All.map
55     (λ {i} p → proj₁ p , lemma-lookupM-checkInsert i i' (proj₁ p) x' h' (insert i' x' h') (proj₂ p) cI≡)
56     (lemma-assoc-domain is' xs' h' ph'))
57 lemma-assoc-domain (i' ∷ is') (x' ∷ xs') h () | just h' | [ ph' ] | ._ | _ | wrong _ _ _
58
59 lemma-map-lookupM-assoc : {m : ℕ} → (i : Fin m) → (x : Carrier) → (h : FinMapMaybe m Carrier) → (h' : FinMapMaybe m Carrier) → checkInsert i x h' ≡ just h → {n : ℕ} → (js : Vec (Fin m) n) → (toList js) in-domain-of h' → map (flip lookupM h) js ≡ map (flip lookupM h') js
60 lemma-map-lookupM-assoc i x h h' ph [] pj = refl
61 lemma-map-lookupM-assoc i x h h' ph (j ∷ js) (All._∷_ (x' , pl) pj) = cong₂ _∷_
62   (trans (lemma-lookupM-checkInsert j i x' x h' h pl ph) (sym pl))
63   (lemma-map-lookupM-assoc i x h h' ph js pj)
64
65 lemma-2 : {m n : ℕ} → (is : Vec (Fin n) m) → (v : Vec Carrier m) → (h : FinMapMaybe n Carrier) → assoc is v ≡ just h → map (flip lookupM h) is ≡ map just v
66 lemma-2 []       []       h p = refl
67 lemma-2 (i ∷ is) (x ∷ xs) h p with assoc is xs | inspect (assoc is) xs
68 lemma-2 (i ∷ is) (x ∷ xs) h () | nothing | _
69 lemma-2 (i ∷ is) (x ∷ xs) h p | just h' | [ ir ] = begin
70   lookupM i h ∷ map (flip lookupM h) is
71     ≡⟨ cong (flip _∷_ (map (flip lookupM h) is)) (lemma-lookupM-assoc i is x xs h (begin
72       assoc (i ∷ is) (x ∷ xs)
73         ≡⟨ cong (flip _>>=_ (checkInsert i x)) ir ⟩
74       checkInsert i x h'
75         ≡⟨ p ⟩
76       just h ∎) ) ⟩
77   just x ∷ map (flip lookupM h) is
78     ≡⟨  cong (_∷_ (just x)) (lemma-map-lookupM-assoc i x h h' p is (lemma-assoc-domain is xs h' ir)) ⟩
79   just x ∷ map (flip lookupM h') is
80     ≡⟨ cong (_∷_ (just x)) (lemma-2 is xs h' ir) ⟩
81   just x ∷ map just xs ∎
82
83 lemma-map-denumerate-enumerate : {m : ℕ} → (as : Vec Carrier m) → map (denumerate as) (enumerate as) ≡ as
84 lemma-map-denumerate-enumerate []       = refl
85 lemma-map-denumerate-enumerate (a ∷ as) = cong (_∷_ a) (begin
86   map (flip lookupVec (a ∷ as)) (tabulate Fin.suc)
87     ≡⟨ cong (map (flip lookupVec (a ∷ as))) (tabulate-∘ Fin.suc id) ⟩
88   map (flip lookupVec (a ∷ as)) (map Fin.suc (tabulate id))
89     ≡⟨ refl ⟩
90   map (flip lookupVec (a ∷ as)) (map Fin.suc (enumerate as))
91     ≡⟨ sym (map-∘ _ _ (enumerate as)) ⟩
92   map (flip lookupVec (a ∷ as) ∘ Fin.suc) (enumerate as)
93     ≡⟨ refl ⟩
94   map (denumerate as) (enumerate as)
95     ≡⟨ lemma-map-denumerate-enumerate as ⟩
96   as ∎)
97
98 theorem-1 : {getlen : ℕ → ℕ} → (get : get-type getlen) → {m : ℕ} → (s : Vec Carrier m) → bff get s (get s) ≡ just s
99 theorem-1 get s = begin
100   bff get s (get s)
101     ≡⟨ cong (bff get s ∘ get) (sym (lemma-map-denumerate-enumerate s)) ⟩
102   bff get s (get (map (denumerate s) (enumerate s)))
103     ≡⟨ cong (bff get s) (free-theorem get (denumerate s) (enumerate s)) ⟩
104   bff get s (map (denumerate s) (get (enumerate s)))
105     ≡⟨ refl ⟩
106   (h′↦r ∘ h↦h′) (assoc (get (enumerate s)) (map (denumerate s) (get (enumerate s))))
107     ≡⟨ cong (h′↦r ∘ h↦h′) (lemma-1 (denumerate s) (get (enumerate s))) ⟩
108   (h′↦r ∘ h↦h′ ∘ just) (restrict (denumerate s) (toList (get (enumerate s))))
109     ≡⟨ refl ⟩
110   (h′↦r ∘ just) (union (restrict (denumerate s) (toList (get (enumerate s)))) (fromFunc (denumerate s)))
111     ≡⟨ cong (h′↦r ∘ just) (lemma-union-restrict (denumerate s) (toList (get (enumerate s)))) ⟩
112   (h′↦r ∘ just) (fromFunc (denumerate s))
113     ≡⟨ refl ⟩
114   just (map (flip lookup (fromFunc (denumerate s))) (enumerate s))
115     ≡⟨ cong just (map-cong (lookup∘tabulate (denumerate s)) (enumerate s)) ⟩
116   just (map (denumerate s) (enumerate s))
117     ≡⟨ cong just (lemma-map-denumerate-enumerate s) ⟩
118   just s ∎
119     where h↦h′ = fmap (flip union (fromFunc (denumerate s)))
120           h′↦r = fmap (flip map (enumerate s) ∘ flip lookupVec)
121
122 lemma-fmap-just : {A B : Set} {f : A → B} {b : B} {ma : Maybe A} → fmap f ma ≡ just b → ∃ λ a → ma ≡ just a
123 lemma-fmap-just {ma = just x}  fmap-f-ma≡just-b = x , refl
124 lemma-fmap-just {ma = nothing} ()
125
126 ∷-injective : {A : Set} {n : ℕ} {x y : A} {xs ys : Vec A n} → (x ∷ xs) ≡ (y ∷ ys) → x ≡ y × xs ≡ ys
127 ∷-injective refl = refl , refl
128
129 map-just-injective : {A : Set} {n : ℕ} {xs ys : Vec A n} → map Maybe.just xs ≡ map Maybe.just ys → xs ≡ ys
130 map-just-injective {xs = []}      {ys = []}       p  = refl
131 map-just-injective {xs = x ∷ xs'} {ys = y ∷ ys'}  p with ∷-injective p
132 map-just-injective {xs = x ∷ xs'} {ys = .x ∷ ys'} p | refl , p' = cong (_∷_ x) (map-just-injective p')
133
134 lemma-union-not-used : {m n : ℕ} {A : Set} (h : FinMapMaybe n A) → (h' : FinMap n A) → (is : Vec (Fin n) m) → (toList is) in-domain-of h → map just (map (flip lookup (union h h')) is) ≡ map (flip lookupM h) is
135 lemma-union-not-used h h' []        p = refl
136 lemma-union-not-used h h' (i ∷ is') (All._∷_ (x , px) p') = cong₂ _∷_ (begin
137       just (lookup i (union h h'))
138         ≡⟨ cong just (lookup∘tabulate (λ j → maybe′ id (lookup j h') (lookupM j h)) i) ⟩
139       just (maybe′ id (lookup i h') (lookupM i h))
140         ≡⟨ cong just (cong (maybe′ id (lookup i h')) px) ⟩
141       just (maybe′ id (lookup i h') (just x))
142         ≡⟨ sym px ⟩
143       lookupM i h ∎)
144   (lemma-union-not-used h h' is' p')
145
146 theorem-2 : {getlen : ℕ → ℕ} (get : get-type getlen) → {m : ℕ} → (v : Vec Carrier (getlen m)) → (s u : Vec Carrier m) → bff get s v ≡ just u → get u ≡ v
147 theorem-2 get v s u p with lemma-fmap-just (proj₂ (lemma-fmap-just p))
148 theorem-2 get v s u p | h , ph = begin
149   get u
150     ≡⟨ just-injective (begin
151       fmap get (just u)
152         ≡⟨ cong (fmap get) (sym p) ⟩
153       fmap get (bff get s v)
154         ≡⟨ cong (fmap get ∘ fmap h′↦r ∘ fmap h↦h′) ph ⟩
155       fmap get (fmap h′↦r (fmap h↦h′ (just h))) ∎) ⟩
156   get (map (flip lookup (h↦h′ h)) s′)
157     ≡⟨ free-theorem get (flip lookup (h↦h′ h)) s′ ⟩
158   map (flip lookup (h↦h′ h)) (get s′)
159      ≡⟨ map-just-injective (begin
160        map just (map (flip lookup (union h g)) (get s′))
161          ≡⟨ lemma-union-not-used h g (get s′) (lemma-assoc-domain (get s′) v h ph) ⟩
162        map (flip lookupM h) (get s′)
163          ≡⟨ lemma-2 (get s′) v h ph ⟩
164        map just v
165          ∎) ⟩
166   v ∎
167     where s′   = enumerate s
168           g    = fromFunc (denumerate s)
169           h↦h′ = flip union g
170           h′↦r = flip map s′ ∘ flip lookupVec