# Data.List.Views

data Balanced : Nat -> Nat -> Type

  Proof that two numbers differ by at most one

  BalancedZ : Balanced 0 0
  BalancedL : Balanced 1 0
  BalancedRec : Balanced n m -> Balanced (S n) (S m)
data Filtered : (a -> a -> Bool) -> List a -> Type

  View for recursively filtering a list by a predicate, applied to the
  first item in each recursively filtered list

  FNil : Filtered p []
  FRec : (lrec : Lazy (Filtered p (filter (\y => p y x) xs))) -> (rrec : Lazy (Filtered p (filter (\y6 => not (p y6 x)) xs))) -> Filtered p (x :: xs)
data SnocList : List a -> Type

  View for traversing a list backwards

  Empty : SnocList []
  Snoc : (rec : SnocList xs) -> SnocList (xs ++ [x])
data Split : List a -> Type

  View for splitting a list in half, non-recursively

  SplitNil : Split []
  SplitOne : Split [x]
  SplitPair : Split (x :: xs ++ y :: ys)
data SplitBalanced : List a -> Type

  View of a list split into two halves

  The lengths of the lists are guaranteed to differ by at most one

  MkSplitBal : Balanced (length xs) (length ys) -> SplitBalanced (xs ++ ys)
data SplitRec : List a -> Type

  View for splitting a list in half, recursively

  This allows us to define recursive functions which repeatedly split lists
  in half, with base cases for the empty and singleton lists.

  SplitRecNil : SplitRec []
  SplitRecOne : SplitRec [x]
  SplitRecPair : (lrec : Lazy (SplitRec lefts)) -> (rrec : Lazy (SplitRec rights)) -> SplitRec (lefts ++ rights)
data VList : List a -> Type

  The `VList` view allows us to recurse on the middle of a list,
  inspecting the front and back elements simultaneously.

  VNil : VList []
  VOne : VList [x]
  VCons : (rec : VList xs) -> VList (x :: xs ++ [y])
filtered : (p : a -> a -> Bool) -> (xs : List a) -> Filtered p xs

  Covering function for the `Filtered` view
  Constructs the view in O(n lg n)

snocList : (xs : List a) -> SnocList xs

  Covering function for the `SnocList` view
  Constructs the view in linear time

split : (xs : List a) -> Split xs

  Covering function for the `Split` view
  Constructs the view in linear time

splitBalanced : (xs : List a) -> SplitBalanced xs

  Covering function for the `SplitBalanced`

  Constructs the view in linear time

splitRec : (xs : List a) -> SplitRec xs

  Covering function for the `SplitRec` view
  Constructs the view in O(n lg n)

vList : (xs : List a) -> VList xs

  Covering function for `VList`
  Constructs the view in linear time.