@@ -4,7 +4,7 @@ import Syntax.PreorderReasoning
5%default total
5%default total
7−-- An isomorphism between two types
7+||| An isomorphism between two types
8data Iso : Type -> Type -> Type where
8data Iso : Type -> Type -> Type where
9 MkIso : (to : a -> b) ->
9 MkIso : (to : a -> b) ->
10 (from : b -> a) ->
10 (from : b -> a) ->
@@ -14,9 +14,11 @@ data Iso : Type -> Type -> Type where
15-- Isomorphism properties
15-- Isomorphism properties
17+||| Isomorphism is reflexive
17isoRefl : Iso a a
18isoRefl : Iso a a
18isoRefl = MkIso id id (\x => refl) (\x => refl)
19isoRefl = MkIso id id (\x => refl) (\x => refl)
21+||| Isomorphism is transitive
20isoTrans : Iso a b -> Iso b c -> Iso a c
22isoTrans : Iso a b -> Iso b c -> Iso a c
21isoTrans (MkIso to from toFrom fromTo) (MkIso to' from' toFrom' fromTo') =
23isoTrans (MkIso to from toFrom fromTo) (MkIso to' from' toFrom' fromTo') =
22 MkIso (\x => to' (to x))
24 MkIso (\x => to' (to x))
@@ -28,11 +30,13 @@ isoTrans (MkIso to from toFrom fromTo) (MkIso to' from' toFrom' fromTo') =
28 (from (to x)) ={ fromTo x }=
30 (from (to x)) ={ fromTo x }=
33+||| Isomorphism is symmetric
31isoSym : Iso a b -> Iso b a
34isoSym : Iso a b -> Iso b a
32isoSym (MkIso to from toFrom fromTo) = MkIso from to fromTo toFrom
35isoSym (MkIso to from toFrom fromTo) = MkIso from to fromTo toFrom
34-- Isomorphisms over sums
37-- Isomorphisms over sums
39+||| Disjunction is commutative
36eitherComm : Iso (Either a b) (Either b a)
40eitherComm : Iso (Either a b) (Either b a)
37eitherComm = MkIso swap swap swapSwap swapSwap
41eitherComm = MkIso swap swap swapSwap swapSwap
38 where swap : Either a' b' -> Either b' a' -- a & b are parameters, so fixed!
42 where swap : Either a' b' -> Either b' a' -- a & b are parameters, so fixed!
@@ -42,6 +46,7 @@ eitherComm = MkIso swap swap swapSwap swapSwap
42 swapSwap (Left x) = refl
46 swapSwap (Left x) = refl
43 swapSwap (Right x) = refl
47 swapSwap (Right x) = refl
49+||| Disjunction is associative
45eitherAssoc : Iso (Either (Either a b) c) (Either a (Either b c))
50eitherAssoc : Iso (Either (Either a b) c) (Either a (Either b c))
46eitherAssoc = MkIso eitherAssoc1 eitherAssoc2 ok1 ok2
51eitherAssoc = MkIso eitherAssoc1 eitherAssoc2 ok1 ok2
47 where eitherAssoc1 : Either (Either a b) c -> Either a (Either b c)
52 where eitherAssoc1 : Either (Either a b) c -> Either a (Either b c)
@@ -64,6 +69,7 @@ eitherAssoc = MkIso eitherAssoc1 eitherAssoc2 ok1 ok2
64 ok2 (Left (Right x)) = refl
69 ok2 (Left (Right x)) = refl
65 ok2 (Right x) = refl
70 ok2 (Right x) = refl
72+||| Disjunction with false is a no-op
67eitherBotLeft : Iso (Either _|_ a) a
73eitherBotLeft : Iso (Either _|_ a) a
68eitherBotLeft = MkIso to from ok1 ok2
74eitherBotLeft = MkIso to from ok1 ok2
69 where to : Either _|_ a -> a
75 where to : Either _|_ a -> a
@@ -77,10 +83,11 @@ eitherBotLeft = MkIso to from ok1 ok2
77 ok2 (Left x) = FalseElim x
83 ok2 (Left x) = FalseElim x
78 ok2 (Right x) = refl
84 ok2 (Right x) = refl
86+||| Disjunction with false is a no-op
80eitherBotRight : Iso (Either a _|_) a
87eitherBotRight : Iso (Either a _|_) a
81eitherBotRight = isoTrans eitherComm eitherBotLeft
88eitherBotRight = isoTrans eitherComm eitherBotLeft
83−
90+||| Isomorphism is a congruence with regards to disjunction
84eitherCong : Iso a a' -> Iso b b' -> Iso (Either a b) (Either a' b')
91eitherCong : Iso a a' -> Iso b b' -> Iso (Either a b) (Either a' b')
85eitherCong {a = a} {a' = a'} {b = b} {b' = b'}
92eitherCong {a = a} {a' = a'} {b = b} {b' = b'}
86 (MkIso to from toFrom fromTo)
93 (MkIso to from toFrom fromTo)
@@ -96,21 +103,25 @@ eitherCong {a = a} {a' = a'} {b = b} {b' = b'}
96 ok2 (Left x) = cong (fromTo x)
103 ok2 (Left x) = cong (fromTo x)
97 ok2 (Right x) = cong (fromTo' x)
104 ok2 (Right x) = cong (fromTo' x)
106+||| Isomorphism is a congruence with regards to disjunction on the left
99eitherCongLeft : Iso a a' -> Iso (Either a b) (Either a' b)
107eitherCongLeft : Iso a a' -> Iso (Either a b) (Either a' b)
100eitherCongLeft i = eitherCong i isoRefl
108eitherCongLeft i = eitherCong i isoRefl
110+||| Isomorphism is a congruence with regards to disjunction on the right
102eitherCongRight : Iso b b' -> Iso (Either a b) (Either a b')
111eitherCongRight : Iso b b' -> Iso (Either a b) (Either a b')
103eitherCongRight i = eitherCong isoRefl i
112eitherCongRight i = eitherCong isoRefl i
105-- Isomorphisms over products
114-- Isomorphisms over products
115+||| Conjunction is commutative
106pairComm : Iso (a, b) (b, a)
116pairComm : Iso (a, b) (b, a)
107pairComm = MkIso swap swap swapSwap swapSwap
117pairComm = MkIso swap swap swapSwap swapSwap
108 where swap : (a', b') -> (b', a')
118 where swap : (a', b') -> (b', a')
109 swap (x, y) = (y, x)
119 swap (x, y) = (y, x)
111 swapSwap : (x : (a', b')) -> swap (swap x) = x
121 swapSwap : (x : (a', b')) -> swap (swap x) = x
112 swapSwap (x, y) = refl
122 swapSwap (x, y) = refl
124+||| Conjunction is associative
114pairAssoc : Iso (a, (b, c)) ((a, b), c)
125pairAssoc : Iso (a, (b, c)) ((a, b), c)
115pairAssoc = MkIso to from ok1 ok2
126pairAssoc = MkIso to from ok1 ok2
@@ -123,20 +134,25 @@ pairAssoc = MkIso to from ok1 ok2
123 ok2 : (x : (a, (b, c))) -> from (to x) = x
134 ok2 : (x : (a, (b, c))) -> from (to x) = x
124 ok2 (x, (y, z)) = refl
135 ok2 (x, (y, z)) = refl
137+||| Conjunction with truth is a no-op
126pairUnitRight : Iso (a, ()) a
138pairUnitRight : Iso (a, ()) a
127pairUnitRight = MkIso fst (\x => (x, ())) (\x => refl) ok
139pairUnitRight = MkIso fst (\x => (x, ())) (\x => refl) ok
128 where ok : (x : (a, ())) -> (fst x, ()) = x
140 where ok : (x : (a, ())) -> (fst x, ()) = x
129 ok (x, ()) = refl
141 ok (x, ()) = refl
143+||| Conjunction with truth is a no-op
131pairUnitLeft : Iso ((), a) a
144pairUnitLeft : Iso ((), a) a
132pairUnitLeft = isoTrans pairComm pairUnitRight
145pairUnitLeft = isoTrans pairComm pairUnitRight
147+||| Conjunction preserves falsehood
134pairBotLeft : Iso (_|_, a) _|_
148pairBotLeft : Iso (_|_, a) _|_
135pairBotLeft = MkIso fst FalseElim (\x => FalseElim x) (\y => FalseElim (fst y))
149pairBotLeft = MkIso fst FalseElim (\x => FalseElim x) (\y => FalseElim (fst y))
151+||| Conjunction preserves falsehood
137pairBotRight : Iso (a, _|_) _|_
152pairBotRight : Iso (a, _|_) _|_
138pairBotRight = isoTrans pairComm pairBotLeft
153pairBotRight = isoTrans pairComm pairBotLeft
155+||| Isomorphism is a congruence with regards to conjunction
140pairCong : Iso a a' -> Iso b b' -> Iso (a, b) (a', b')
156pairCong : Iso a a' -> Iso b b' -> Iso (a, b) (a', b')
141pairCong {a = a} {a' = a'} {b = b} {b' = b'}
157pairCong {a = a} {a' = a'} {b = b} {b' = b'}
142 (MkIso to from toFrom fromTo)
158 (MkIso to from toFrom fromTo)
@@ -155,13 +171,16 @@ pairCong {a = a} {a' = a'} {b = b} {b' = b'}
155 rewrite fromTo' y in
171 rewrite fromTo' y in
174+||| Isomorphism is a congruence with regards to conjunction on the left
158pairCongLeft : Iso a a' -> Iso (a, b) (a', b)
175pairCongLeft : Iso a a' -> Iso (a, b) (a', b)
159pairCongLeft i = pairCong i isoRefl
176pairCongLeft i = pairCong i isoRefl
178+||| Isomorphism is a congruence with regards to conjunction on the right
161pairCongRight : Iso b b' -> Iso (a, b) (a, b')
179pairCongRight : Iso b b' -> Iso (a, b) (a, b')
162pairCongRight = pairCong isoRefl
180pairCongRight = pairCong isoRefl
164-- Distributivity of products over sums
182-- Distributivity of products over sums
183+||| Products distribute over sums
165distribLeft : Iso (Either a b, c) (Either (a, c) (b, c))
184distribLeft : Iso (Either a b, c) (Either (a, c) (b, c))
166distribLeft = MkIso to from toFrom fromTo
185distribLeft = MkIso to from toFrom fromTo
167 where to : (Either a b, c) -> Either (a, c) (b, c)
186 where to : (Either a b, c) -> Either (a, c) (b, c)
@@ -177,20 +196,24 @@ distribLeft = MkIso to from toFrom fromTo
177 fromTo (Left x, y) = refl
196 fromTo (Left x, y) = refl
178 fromTo (Right x, y) = refl
197 fromTo (Right x, y) = refl
199+||| Products distribute over sums
180distribRight : Iso (a, Either b c) (Either (a, b) (a, c))
200distribRight : Iso (a, Either b c) (Either (a, b) (a, c))
181distribRight {a} {b} {c} = (pairComm `isoTrans` distribLeft) `isoTrans` eitherCong pairComm pairComm
201distribRight {a} {b} {c} = (pairComm `isoTrans` distribLeft) `isoTrans` eitherCong pairComm pairComm
184-- Enable preorder reasoning syntax over isomorphisms
204-- Enable preorder reasoning syntax over isomorphisms
205+||| Used for preorder reasoning syntax. Not intended for direct use.
185qed : (a : Type) -> Iso a a
206qed : (a : Type) -> Iso a a
186qed a = isoRefl
207qed a = isoRefl
209+||| Used for preorder reasoning syntax. Not intended for direct use.
188step : (a : Type) -> Iso a b -> Iso b c -> Iso a c
210step : (a : Type) -> Iso a b -> Iso b c -> Iso a c
189step a iso1 iso2 = isoTrans iso1 iso2
211step a iso1 iso2 = isoTrans iso1 iso2
193-- Isomorphisms over Maybe
215-- Isomorphisms over Maybe
216+||| Isomorphism is a congruence with respect to Maybe
194maybeCong : Iso a b -> Iso (Maybe a) (Maybe b)
217maybeCong : Iso a b -> Iso (Maybe a) (Maybe b)
195maybeCong {a} {b} (MkIso to from toFrom fromTo) = MkIso (map to) (map from) ok1 ok2
218maybeCong {a} {b} (MkIso to from toFrom fromTo) = MkIso (map to) (map from) ok1 ok2
196 where ok1 : (y : Maybe b) -> map to (map from y) = y
219 where ok1 : (y : Maybe b) -> map to (map from y) = y
@@ -200,6 +223,7 @@ maybeCong {a} {b} (MkIso to from toFrom fromTo) = MkIso (map to) (map from) ok1
200 ok2 Nothing = refl
223 ok2 Nothing = refl
201 ok2 (Just x) = (Just (from (to x))) ={ cong (fromTo x) }= (Just x) QED
224 ok2 (Just x) = (Just (from (to x))) ={ cong (fromTo x) }= (Just x) QED
226+||| `Maybe a` is the same as `Either a ()`
203maybeEither : Iso (Maybe a) (Either a ())
227maybeEither : Iso (Maybe a) (Either a ())
204maybeEither = MkIso to from iso1 iso2
228maybeEither = MkIso to from iso1 iso2
205 where to : Maybe a -> Either a ()
229 where to : Maybe a -> Either a ()
@@ -215,6 +239,7 @@ maybeEither = MkIso to from iso1 iso2
215 iso2 Nothing = refl
239 iso2 Nothing = refl
216 iso2 (Just x) = refl
240 iso2 (Just x) = refl
242+||| Maybe of void is just unit
218maybeVoidUnit : Iso (Maybe _|_) ()
243maybeVoidUnit : Iso (Maybe _|_) ()
219maybeVoidUnit = (Maybe _|_) ={ maybeEither }=
244maybeVoidUnit = (Maybe _|_) ={ maybeEither }=
220 (Either _|_ ()) ={ eitherBotLeft }=
245 (Either _|_ ()) ={ eitherBotLeft }=