@@ -4,7 +4,7 @@ import Syntax.PreorderReasoning
44
55%default total
66
7−-- An isomorphism between two types
7+||| An isomorphism between two types
88data Iso : Type -> Type -> Type where
99 MkIso : (to : a -> b) ->
1010 (from : b -> a) ->
@@ -14,9 +14,11 @@ data Iso : Type -> Type -> Type where
1414
1515-- Isomorphism properties
1616
17+||| Isomorphism is reflexive
1718isoRefl : Iso a a
1819isoRefl = MkIso id id (\x => refl) (\x => refl)
1920
21+||| Isomorphism is transitive
2022isoTrans : Iso a b -> Iso b c -> Iso a c
2123isoTrans (MkIso to from toFrom fromTo) (MkIso to' from' toFrom' fromTo') =
2224 MkIso (\x => to' (to x))
@@ -28,11 +30,13 @@ isoTrans (MkIso to from toFrom fromTo) (MkIso to' from' toFrom' fromTo') =
2830 (from (to x)) ={ fromTo x }=
2931 x QED)
3032
33+||| Isomorphism is symmetric
3134isoSym : Iso a b -> Iso b a
3235isoSym (MkIso to from toFrom fromTo) = MkIso from to fromTo toFrom
3336
3437-- Isomorphisms over sums
3538
39+||| Disjunction is commutative
3640eitherComm : Iso (Either a b) (Either b a)
3741eitherComm = MkIso swap swap swapSwap swapSwap
3842 where swap : Either a' b' -> Either b' a' -- a & b are parameters, so fixed!
@@ -42,6 +46,7 @@ eitherComm = MkIso swap swap swapSwap swapSwap
4246 swapSwap (Left x) = refl
4347 swapSwap (Right x) = refl
4448
49+||| Disjunction is associative
4550eitherAssoc : Iso (Either (Either a b) c) (Either a (Either b c))
4651eitherAssoc = MkIso eitherAssoc1 eitherAssoc2 ok1 ok2
4752 where eitherAssoc1 : Either (Either a b) c -> Either a (Either b c)
@@ -64,6 +69,7 @@ eitherAssoc = MkIso eitherAssoc1 eitherAssoc2 ok1 ok2
6469 ok2 (Left (Right x)) = refl
6570 ok2 (Right x) = refl
6671
72+||| Disjunction with false is a no-op
6773eitherBotLeft : Iso (Either _|_ a) a
6874eitherBotLeft = MkIso to from ok1 ok2
6975 where to : Either _|_ a -> a
@@ -77,10 +83,11 @@ eitherBotLeft = MkIso to from ok1 ok2
7783 ok2 (Left x) = FalseElim x
7884 ok2 (Right x) = refl
7985
86+||| Disjunction with false is a no-op
8087eitherBotRight : Iso (Either a _|_) a
8188eitherBotRight = isoTrans eitherComm eitherBotLeft
8289
83−
90+||| Isomorphism is a congruence with regards to disjunction
8491eitherCong : Iso a a' -> Iso b b' -> Iso (Either a b) (Either a' b')
8592eitherCong {a = a} {a' = a'} {b = b} {b' = b'}
8693 (MkIso to from toFrom fromTo)
@@ -96,21 +103,25 @@ eitherCong {a = a} {a' = a'} {b = b} {b' = b'}
96103 ok2 (Left x) = cong (fromTo x)
97104 ok2 (Right x) = cong (fromTo' x)
98105
106+||| Isomorphism is a congruence with regards to disjunction on the left
99107eitherCongLeft : Iso a a' -> Iso (Either a b) (Either a' b)
100108eitherCongLeft i = eitherCong i isoRefl
101109
110+||| Isomorphism is a congruence with regards to disjunction on the right
102111eitherCongRight : Iso b b' -> Iso (Either a b) (Either a b')
103112eitherCongRight i = eitherCong isoRefl i
104113
105114-- Isomorphisms over products
115+||| Conjunction is commutative
106116pairComm : Iso (a, b) (b, a)
107117pairComm = MkIso swap swap swapSwap swapSwap
108118 where swap : (a', b') -> (b', a')
109119 swap (x, y) = (y, x)
110−
120+
111121 swapSwap : (x : (a', b')) -> swap (swap x) = x
112122 swapSwap (x, y) = refl
113123
124+||| Conjunction is associative
114125pairAssoc : Iso (a, (b, c)) ((a, b), c)
115126pairAssoc = MkIso to from ok1 ok2
116127 where
@@ -123,20 +134,25 @@ pairAssoc = MkIso to from ok1 ok2
123134 ok2 : (x : (a, (b, c))) -> from (to x) = x
124135 ok2 (x, (y, z)) = refl
125136
137+||| Conjunction with truth is a no-op
126138pairUnitRight : Iso (a, ()) a
127139pairUnitRight = MkIso fst (\x => (x, ())) (\x => refl) ok
128140 where ok : (x : (a, ())) -> (fst x, ()) = x
129141 ok (x, ()) = refl
130142
143+||| Conjunction with truth is a no-op
131144pairUnitLeft : Iso ((), a) a
132145pairUnitLeft = isoTrans pairComm pairUnitRight
133146
147+||| Conjunction preserves falsehood
134148pairBotLeft : Iso (_|_, a) _|_
135149pairBotLeft = MkIso fst FalseElim (\x => FalseElim x) (\y => FalseElim (fst y))
136150
151+||| Conjunction preserves falsehood
137152pairBotRight : Iso (a, _|_) _|_
138153pairBotRight = isoTrans pairComm pairBotLeft
139154
155+||| Isomorphism is a congruence with regards to conjunction
140156pairCong : Iso a a' -> Iso b b' -> Iso (a, b) (a', b')
141157pairCong {a = a} {a' = a'} {b = b} {b' = b'}
142158 (MkIso to from toFrom fromTo)
@@ -155,13 +171,16 @@ pairCong {a = a} {a' = a'} {b = b} {b' = b'}
155171 rewrite fromTo' y in
156172 refl
157173
174+||| Isomorphism is a congruence with regards to conjunction on the left
158175pairCongLeft : Iso a a' -> Iso (a, b) (a', b)
159176pairCongLeft i = pairCong i isoRefl
160177
178+||| Isomorphism is a congruence with regards to conjunction on the right
161179pairCongRight : Iso b b' -> Iso (a, b) (a, b')
162180pairCongRight = pairCong isoRefl
163181
164182-- Distributivity of products over sums
183+||| Products distribute over sums
165184distribLeft : Iso (Either a b, c) (Either (a, c) (b, c))
166185distribLeft = MkIso to from toFrom fromTo
167186 where to : (Either a b, c) -> Either (a, c) (b, c)
@@ -177,20 +196,24 @@ distribLeft = MkIso to from toFrom fromTo
177196 fromTo (Left x, y) = refl
178197 fromTo (Right x, y) = refl
179198
199+||| Products distribute over sums
180200distribRight : Iso (a, Either b c) (Either (a, b) (a, c))
181201distribRight {a} {b} {c} = (pairComm `isoTrans` distribLeft) `isoTrans` eitherCong pairComm pairComm
182202
183203
184204-- Enable preorder reasoning syntax over isomorphisms
205+||| Used for preorder reasoning syntax. Not intended for direct use.
185206qed : (a : Type) -> Iso a a
186207qed a = isoRefl
187208
209+||| Used for preorder reasoning syntax. Not intended for direct use.
188210step : (a : Type) -> Iso a b -> Iso b c -> Iso a c
189211step a iso1 iso2 = isoTrans iso1 iso2
190212
191213
192214
193215-- Isomorphisms over Maybe
216+||| Isomorphism is a congruence with respect to Maybe
194217maybeCong : Iso a b -> Iso (Maybe a) (Maybe b)
195218maybeCong {a} {b} (MkIso to from toFrom fromTo) = MkIso (map to) (map from) ok1 ok2
196219 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
200223 ok2 Nothing = refl
201224 ok2 (Just x) = (Just (from (to x))) ={ cong (fromTo x) }= (Just x) QED
202225
226+||| `Maybe a` is the same as `Either a ()`
203227maybeEither : Iso (Maybe a) (Either a ())
204228maybeEither = MkIso to from iso1 iso2
205229 where to : Maybe a -> Either a ()
@@ -215,6 +239,7 @@ maybeEither = MkIso to from iso1 iso2
215239 iso2 Nothing = refl
216240 iso2 (Just x) = refl
217241
242+||| Maybe of void is just unit
218243maybeVoidUnit : Iso (Maybe _|_) ()
219244maybeVoidUnit = (Maybe _|_) ={ maybeEither }=
220245 (Either _|_ ()) ={ eitherBotLeft }=