### Sequences of values

[
  Funcon length
  Funcon index
  Funcon is-in
  Funcon first
  Funcon second
  Funcon third
  Funcon first-n
  Funcon drop-first-n
  Funcon reverse
  Funcon n-of
  Funcon intersperse
]

/*
  Sequences of two or more values are not themselves values, nor is the empty
  sequence a value. However, sequences can be provided to funcons as arguments,
  and returned as results. Many operations on composite values can be expressed
  by extracting their components as sequences, operating on the sequences, then
  forming the required composite values from the resulting sequences.
  
  A sequence with elements `X1`, ..., `Xn` is written `X1,...,Xn`.
  A sequence with a single element `X` is identified with (and written) `X`.
  An empty sequence is indicated by the absence of a term.
  Any sequence `X*` can be enclosed in parentheses `(X*)`, e.g.:
  `( )`, `(1)`, `(1,2,3)`. Superfluous commas are ignored.
  
  The elements of a type sequence `T1,...,Tn` are the value sequences `V1,...,Vn`
  where `V1:T1`, ..., `Vn:Tn`. The only element of the empty type sequence `( )`
  is the empty value sequence `( )`.
  
  `(T)^N` is equivalent to `T,...,T` with `N` occurrences of `T`.
  `(T)*` is equivalent to the union of all `(T)^N` for `N`>=0,
  `(T)+` is equivalent to the union of all `(T)^N` for `N`>=1, and
  `(T)?` is equivalent to `T | ( )`.
  The parentheses around `T` above can be omitted when they are not needed for
  disambiguation.
    
  (Non-trivial) sequence types are not values, so not included in `types`.
*/


Meta-variables 
  T, T′ <: values


Funcon
  length(_:values*) : =>natural-numbers
/*
  `length(V*)` gives the number of elements in `V*`.
*/
Rule
  length( ) ~> 0
Rule
  length(V:values, V*:values*) ~> natural-successor(length(V*))


Funcon
  is-in(_:values, _:values*) : =>booleans
Rule
  is-in(V:values ,V′:values, V*:values*) ~> or(is-equal(V, V′), is-in(V, V*))
Rule
  is-in(V:values, ( )) ~> false


#### Sequence indexing

Funcon
  index(_:natural-numbers, _:values*) : =>values? 
/*
  `index(N, V*)` gives the `N`th element of `V*`, if it exists, otherwise `( )`.
*/
Rule
  index(1, V:values, V*:values*) ~> V
Rule
  natural-predecessor(N) ~> N′
  -----------------------------------------------------------------
  index(N:positive-integers, _:values, V*:values*) ~> index(N′, V*)
Rule
  index(0, V*:values*) ~> ( )
Rule
  index(_:positive-integers, ( )) ~> ( )


// Total indexing funcons:

Funcon 
  first(_:T, _:values*) : =>T
Rule
  first(V:T, V*:values*) ~> V

Funcon 
  second(_:values, _:T, _:values*) : =>T
Rule
  second(_:values, V:T, V*:values*) ~> V

Funcon 
  third(_:values, _:values, _:T, _:values*) : =>T
Rule
  third(_:values, _:values, V:T, V*:values*) ~> V


#### Homogeneous sequences


Funcon
  first-n(_:natural-numbers, _:(T)*) : =>(T)*
Rule
  first-n(0, V*:(T)*) ~> ( )
Rule
  natural-predecessor(N) ~> N′
  -----------------------------------------------------------------
  first-n(N:positive-integers, V:T, V*:(T)*) ~> (V,first-n(N′, V*))
Rule
  first-n(N:positive-integers, ( )) ~> ( )


Funcon
  drop-first-n(_:natural-numbers, _:(T)*) : =>(T)*
Rule
  drop-first-n(0, V*:(T)*) ~> V*
Rule
  natural-predecessor(N) ~> N′
  -----------------------------------------------------------------------
  drop-first-n(N:positive-integers, _:T, V*:(T)*) ~> drop-first-n(N′, V*)
Rule
  drop-first-n(N:positive-integers, ( )) ~> ( )


Funcon
  reverse(_:(T)*) : =>(T)*
Rule
  reverse( ) ~> ( )
Rule
  reverse(V:T, V*:(T)*) ~> (reverse(V*), V)


Funcon
  n-of(N:natural-numbers, V:T) : =>(T)*
Rule
  n-of(0, _:T) ~> ( )
Rule
  natural-predecessor(N) ~> N′
  --------------------------------------------------
  n-of(N:positive-integers, V:T) ~> (V, n-of(N′, V))


Funcon
  intersperse(_:T′, _:(T)*) : =>(T, (T′, T)*)?
Rule
  intersperse(_:T′, ( )) ~> ( )
Rule
  intersperse(_:T′, V) ~> V
Rule
  intersperse(V′:T′, V1:T, V2:T, V*:(T)*) ~> (V1, V′, intersperse(V′, V2, V*))