Skip to content

Commit 583442b

Browse files
buzdengallais
andauthored
[ contrib ] Arithmetic on Fin (#830)
Co-authored-by: Guillaume ALLAIS <[email protected]>
1 parent 48dc732 commit 583442b

File tree

7 files changed

+500
-71
lines changed

7 files changed

+500
-71
lines changed

libs/base/Data/Fin.idr

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ data Fin : (n : Nat) -> Type where
1717
FZ : Fin (S k)
1818
FS : Fin k -> Fin (S k)
1919

20+
||| Cast between Fins with equal indices
21+
public export
22+
cast : {n : Nat} -> (0 eq : m = n) -> Fin m -> Fin n
23+
cast {n = S _} eq FZ = FZ
24+
cast {n = Z} eq FZ impossible
25+
cast {n = S _} eq (FS k) = FS (cast (succInjective _ _ eq) k)
26+
cast {n = Z} eq (FS k) impossible
27+
2028
export
2129
Uninhabited (Fin Z) where
2230
uninhabited FZ impossible
@@ -176,3 +184,99 @@ DecEq (Fin n) where
176184
= case decEq f f' of
177185
Yes p => Yes $ cong FS p
178186
No p => No $ p . fsInjective
187+
188+
namespace Equality
189+
190+
||| Pointwise equality of Fins
191+
||| It is sometimes complicated to prove equalities on type-changing
192+
||| operations on Fins.
193+
||| This inductive definition can be used to simplify proof. We can
194+
||| recover proofs of equalities by using `homoPointwiseIsEqual`.
195+
public export
196+
data Pointwise : Fin m -> Fin n -> Type where
197+
FZ : Pointwise FZ FZ
198+
FS : Pointwise k l -> Pointwise (FS k) (FS l)
199+
200+
infix 6 ~~~
201+
||| Convenient infix notation for the notion of pointwise equality of Fins
202+
public export
203+
(~~~) : Fin m -> Fin n -> Type
204+
(~~~) = Pointwise
205+
206+
||| Pointwise equality is reflexive
207+
export
208+
reflexive : {k : Fin m} -> k ~~~ k
209+
reflexive {k = FZ} = FZ
210+
reflexive {k = FS k} = FS reflexive
211+
212+
||| Pointwise equality is symmetric
213+
export
214+
symmetric : k ~~~ l -> l ~~~ k
215+
symmetric FZ = FZ
216+
symmetric (FS prf) = FS (symmetric prf)
217+
218+
||| Pointwise equality is transitive
219+
export
220+
transitive : j ~~~ k -> k ~~~ l -> j ~~~ l
221+
transitive FZ FZ = FZ
222+
transitive (FS prf) (FS prg) = FS (transitive prf prg)
223+
224+
||| Pointwise equality is compatible with cast
225+
export
226+
castEq : {k : Fin m} -> (0 eq : m = n) -> cast eq k ~~~ k
227+
castEq {k = FZ} Refl = FZ
228+
castEq {k = FS k} Refl = FS (castEq _)
229+
230+
||| The actual proof used by cast is irrelevant
231+
export
232+
congCast : {n, q : Nat} -> {k : Fin m} -> {l : Fin p} ->
233+
{0 eq1 : m = n} -> {0 eq2 : p = q} ->
234+
k ~~~ l ->
235+
cast eq1 k ~~~ cast eq2 l
236+
congCast eq = transitive (castEq _) (transitive eq $ symmetric $ castEq _)
237+
238+
||| Last is congruent wrt index equality
239+
export
240+
congLast : {m, n : Nat} -> (0 _ : m = n) -> last {n=m} ~~~ last {n}
241+
congLast {m = Z} {n = Z} eq = reflexive
242+
congLast {m = S _} {n = S _} eq = FS (congLast (succInjective _ _ eq))
243+
244+
export
245+
congShift : (m : Nat) -> k ~~~ l -> shift m k ~~~ shift m l
246+
congShift Z prf = prf
247+
congShift (S m) prf = FS (congShift m prf)
248+
249+
||| WeakenN is congruent wrt pointwise equality
250+
export
251+
congWeakenN : k ~~~ l -> weakenN n k ~~~ weakenN n l
252+
congWeakenN FZ = FZ
253+
congWeakenN (FS prf) = FS (congWeakenN prf)
254+
255+
||| Pointwise equality is propositional equality on Fins that have the same type
256+
export
257+
homoPointwiseIsEqual : {0 k, l : Fin m} -> k ~~~ l -> k === l
258+
homoPointwiseIsEqual FZ = Refl
259+
homoPointwiseIsEqual (FS prf) = cong FS (homoPointwiseIsEqual prf)
260+
261+
||| Pointwise equality is propositional equality modulo transport on Fins that
262+
||| have provably equal types
263+
export
264+
hetPointwiseIsTransport :
265+
{0 k : Fin m} -> {0 l : Fin n} ->
266+
(eq : m === n) -> k ~~~ l -> k === rewrite eq in l
267+
hetPointwiseIsTransport Refl = homoPointwiseIsEqual
268+
269+
export
270+
finToNatQuotient : k ~~~ l -> finToNat k === finToNat l
271+
finToNatQuotient FZ = Refl
272+
finToNatQuotient (FS prf) = cong S (finToNatQuotient prf)
273+
274+
export
275+
weakenNeutral : (k : Fin n) -> weaken k ~~~ k
276+
weakenNeutral FZ = FZ
277+
weakenNeutral (FS k) = FS (weakenNeutral k)
278+
279+
export
280+
weakenNNeutral : (0 m : Nat) -> (k : Fin n) -> weakenN m k ~~~ k
281+
weakenNNeutral m FZ = FZ
282+
weakenNNeutral m (FS k) = FS (weakenNNeutral m k)

0 commit comments

Comments
 (0)