# Control.Isomorphism.Vect

congExtUnindex : (f : Fin n -> a) -> (g : Fin n -> a) -> ((i : Fin n) -> f i = g i) -> unindex f = unindex g

  If `f` and `g` are extensionally equal (equal outputs for all inputs), then `unindex f = unindex g`.

consPair : Iso (Vect (S n) a) (a, Vect n a)

  Moves between `x :: xs` and `(x, xs)`.

fromIndices : (Fin o -> Fin i) -> Vect i a -> Vect o a

  Given a function that computes an index in the input from the index in the output, produce a `Vect o` of elements from the input.

  This is the map function of the functor `\i => Vect i a` from `\i, o => Fin o -> Fin i` to `\i, o => Vect i a -> Vect o a`.

fromIndicesFromIndices : (to : Fin n -> Fin n) -> (from : Fin n -> Fin n) -> (fromTo : (i : Fin n) -> from (to i) = i) -> (xs : Vect n a) -> fromIndices to (fromIndices from xs) = xs
indexFromIndices : (f : Fin o -> Fin i) -> (xs : Vect i a) -> (n : Fin o) -> index n (fromIndices f xs) = index (f n) xs
indexPermuted : (permutation : Iso (Fin n) (Fin n)) -> (i : Fin n) -> (xs : Vect n a) -> index i xs = index (to permutation i) (to (permuted permutation) xs)
indexUnindex : (i : Fin n) -> (f : Fin n -> a) -> index i (unindex f) = f i

  Indexing into the table of outputs of `f` is like calling `f` itself.

injExtUnindex : (f : Fin n -> a) -> (g : Fin n -> a) -> (unindex f = unindex g) -> (i : Fin n) -> f i = g i

  Functions with the same tables are the same themselves.

nilUnit : Iso (Vect 0 a) ()

  `Vect Z a` has only one value: `[]`.

oneIdentity : Iso (Vect 1 a) a

  A `Vect (S Z) a` is just an `a`.

permuted : (permutation : Iso (Fin n) (Fin n)) -> Iso (Vect n a) (Vect n a)

  Given a permutation of the indices, provide an `Iso` that can permute a `Vect n` the "same" way. More precisely,
  if the index `i` is sent to `j`, then the element at index `i` ends up at index `j` (`indexPermuted`). An
  `Iso (Fin n) (Fin n)` represents a permutation of the integers `[0, n)` because it ensures that no elements
  are "lost" or "duplicated".

  Note this has the opposite behavior to `fromIndices`. This function is more "visceral"; it can be imagined
  as shuffling a `Vect` in the same way `map (to permutation)` shuffles `range`. Or, in more categorical terms,
  `fromIndices` represents a contravariant functor from the category `\i, o => Fin i -> Fin o` to `\i, o => Vect i a -> Vect o a`,
  and `permuted` represents that functor restricted to isomorphisms and made covariant with `isoSym`.

      to (permuted (stimes 2 rotatedDown)) [1, 2, 3, 4, 5] == [3, 4, 5, 1, 2]
      to (permuted (swapped 3 0))          [1, 2, 3, 4, 5] == [4, 2, 3, 1, 5]

  permutation

    an `Iso` representing the transformation on the indices

permutedSym : (permutation : Iso (Fin n) (Fin n)) -> permuted (isoSym permutation) = isoSym (permuted permutation)
rectangular : Iso (Vect (n * m) a) (Vect n (Vect m a))

  An `Iso` based on `unconcat` and `concat`.

      from rectangular [[1,2,3],[4,5,6]]

splitPair : Iso (Vect (n + m) a) (Vect n a, Vect m a)

  An `Iso` based on `splitAt` and `(++)`.

transposition : Iso (Vect o (Vect i a)) (Vect i (Vect o a))

  An `Iso` based on `transpose`.

unconcat : Vect (n * m) a -> Vect n (Vect m a)

  Split the `Vect` every `m` elements, making `n` `Vect m a`s.
  The result is rectangular and has the same order as the original.

  This is the inverse of `concat`.

unindex : (Fin n -> a) -> Vect n a

  Go through all possible inputs and tabulate the outputs in a `Vect`.

  Or: turn a function from indices to values into a `Vect`.
  Or: the inverse of `index`.

unindexIndex : (xs : Vect n a) -> unindex (\i => index i xs) = xs

  A simpler version of `unindexIndex'` which only proves that `unindex` is the inverse of `index`.

unindexIndex' : (xs : Vect n a) -> (f : Fin n -> a) -> ((i : Fin n) -> f i = index i xs) -> unindex f = xs

  Given a function `f`, a `Vect` `xs`, and a proof that calling `f` gives the same result as indexing into `xs`,
  prove that `xs` is the table of outputs of `f`.

zipped : Iso (Vect n a, Vect n b) (Vect n (a, b))

  An `Iso` based on `zip` and `unzip`.

zipped3 : Iso (Vect n a, Vect n b, Vect n c) (Vect n (a, b, c))

  An `Iso` based on `zip3` and `unzip3`.