0

In Idris, can you establish an isomorphism between Fin n and (x ** So (x < n))? (I don't actually know Idris, so those types may not be valid. The general idea is that we have a data type that is guaranteed to be less than n by construction, and another that is guaranteed to be less than n by test.)

Cactus
  • 27,075
  • 9
  • 69
  • 149
PyRulez
  • 10,513
  • 10
  • 42
  • 87

1 Answers1

2

Here's a proof in Idris 0.10.2 As you can see, roundtrip2 is the only tricky proof.

import Data.Fin
%default total

Bound : Nat -> Type
Bound n = DPair Nat (\x => x `LT` n)

bZ : Bound (S n)
bZ = (0 ** LTESucc LTEZero)

bS : Bound n -> Bound (S n)
bS (x ** bound) = (S x ** LTESucc bound)

fromFin : Fin n -> Bound n
fromFin FZ = bZ
fromFin (FS k) = bS (fromFin k)

toFin : Bound n -> Fin n
toFin (Z ** LTEZero) impossible
toFin {n = S n} (Z ** bound) = FZ
toFin (S x ** LTESucc bound) = FS (toFin (x ** bound))

roundtrip1 : {n : Nat} -> (k : Bound n) -> fromFin (toFin k) = k
roundtrip1 (Z ** LTEZero) impossible
roundtrip1 {n = S n} (Z ** LTESucc LTEZero) = Refl
roundtrip1 (S x ** LTESucc bound) = rewrite (roundtrip1 (x ** bound)) in Refl

roundtrip2 : {n : Nat} -> (k : Fin n) -> toFin (fromFin k) = k
roundtrip2 FZ = Refl
roundtrip2 (FS k) = rewrite (lemma (fromFin k)) in cong {f = FS} (roundtrip2 k)
  where
    lemma : {n : Nat} -> (k : Bound n) -> toFin (bS k) = FS (toFin k)
    lemma (x ** pf) = Refl

If what you have is a non-propositional So (x < n) instead of x `LT` n, you'll need to transform it to the proof form. This one I was able to do like this:

import Data.So

%default total

stepBack : So (S x < S y) -> So (x < y)
stepBack {x = x} {y = y} so with (compare x y)
  | LT = so
  | EQ = so
  | GT = so

correct : So (x < y) -> x `LT` y
correct {x = Z}   {y = Z}     Oh impossible
correct {x = S _} {y = Z}     Oh impossible
correct {x = Z}   {y = S _} so = LTESucc LTEZero
correct {x = S x} {y = S y} so = LTESucc $ correct $ stepBack so
Cactus
  • 27,075
  • 9
  • 69
  • 149
  • 1
    Actually I take it back -- writing `So (x < n) -> x \`LT\` n`, or even the supposed-to-be-a-bit-simpler `So (x <= n) -> x \`LTE\` n` proof is quite tricky! – Cactus Mar 22 '16 at 11:39
  • @PyRulez: `So` is it clear now how you'd combine the two bits above into what you are after? – Cactus Mar 23 '16 at 05:37