(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From mathcomp
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
(******************************************************************************)
(* Tuples, i.e., sequences with a fixed (known) length. We define:            *)
(*         n.-tuple T == the type of n-tuples of elements of type T.          *)
(*       [tuple of s] == the tuple whose underlying sequence (value) is s.    *)
(*                       The size of s must be known: specifically, Coq must  *)
(*                       be able to infer a Canonical tuple projecting on s.  *)
(*         in_tuple s == the (size s)-tuple with value s.                     *)
(*            [tuple] == the empty tuple.                                     *)
(* [tuple x1; ..; xn] == the explicit n.-tuple <x1; ..; xn>.                  *)
(*  [tuple E | i < n] == the n.-tuple with general term E (i : 'I_n is bound  *)
(*                       in E).                                               *)
(*        tcast Emn t == the m-tuple t cast as an n-tuple using Emn : m = n.  *)
(* As n.-tuple T coerces to seq t, all seq operations (size, nth, ...) can be *)
(* applied to t : n.-tuple T; we provide a few specialized instances when     *)
(* avoids the need for a default value.                                       *)
(*            tsize t == the size of t (the n in n.-tuple T)                  *)
(*           tnth t i == the i'th component of t, where i : 'I_n.             *)
(*         [tnth t i] == the i'th component of t, where i : nat and i < n     *)
(*                       is convertible to true.                              *)
(*            thead t == the first element of t, when n is m.+1 for some m.   *)
(* Most seq constructors (cons, behead, cat, rcons, belast, take, drop, rot,  *)
(* map, ...) can be used to build tuples via the [tuple of s] construct.      *)
(*   Tuples are actually a subType of seq, and inherit all combinatorial      *)
(* structures, including the finType structure.                               *)
(*   Some useful lemmas and definitions:                                      *)
(*     tuple0 : [tuple] is the only 0.-tuple                                  *)
(*     tupleP : elimination view for n.+1.-tuple                              *)
(*     ord_tuple n : the n.-tuple of all i : 'I_n                             *)
(******************************************************************************)
Section Def.
Variables (n : nat) (T : Type).
Structure tuple_of : Type := Tuple {tval :> seq T; _ : size tval == n}.
Canonical tuple_subType := Eval hnf in [subType for tval].
Implicit Type t : tuple_of.
Definition tsize of tuple_of := n.

(* Specifications: *)
Lemma size_tuple t : size t = n.
Lemma eq_from_tnth t1 t2 : tnth t1 =1 tnth t2 -> t1 = t2.
Definition tuple t mkT : tuple_of :=
mkT (let: Tuple _ tP := t return size t == n in tP).
Lemma tupleE t : tuple (fun sP => @Tuple t sP) = t.
Lemma tnth_map f t i : tnth [tuple of map f t] i = f (tnth t i) :> rT.
Lemma existsb_tnth a t : [exists i, a (tnth t i)] = has a t.
Lemma seq_tnthP (s : seq T) x : x \in s -> {i | x = tnth (in_tuple s) i}.
End EqTuple.