Idris2/libs/base/Data/List/Views.idr
2020-07-07 10:48:23 +01:00

97 lines
3.3 KiB
Idris

module Data.List.Views
import Control.WellFounded
import Data.List
import Data.Nat
import Data.Nat.Views
%default total
lengthSuc : (xs : List a) -> (y : a) -> (ys : List a) ->
length (xs ++ (y :: ys)) = S (length (xs ++ ys))
lengthSuc [] _ _ = Refl
lengthSuc (x :: xs) y ys = cong S (lengthSuc xs y ys)
lengthLT : (xs : List a) -> (ys : List a) ->
LTE (length xs) (length (ys ++ xs))
lengthLT xs [] = lteRefl
lengthLT xs (x :: ys) = lteSuccRight (lengthLT _ _)
smallerLeft : (ys : List a) -> (y : a) -> (zs : List a) ->
LTE (S (S (length ys))) (S (length (ys ++ (y :: zs))))
smallerLeft [] y zs = LTESucc (LTESucc LTEZero)
smallerLeft (z :: ys) y zs = LTESucc (smallerLeft ys _ _)
smallerRight : (ys : List a) -> (zs : List a) ->
LTE (S (S (length zs))) (S (length (ys ++ (y :: zs))))
smallerRight {y} ys zs = rewrite lengthSuc ys y zs in
(LTESucc (LTESucc (lengthLT _ _)))
||| View for splitting a list in half, non-recursively
public export
data Split : List a -> Type where
SplitNil : Split []
SplitOne : (x : a) -> Split [x]
SplitPair : (x : a) -> (xs : List a) ->
(y : a) -> (ys : List a) ->
Split (x :: xs ++ y :: ys)
splitHelp : (head : a) ->
(xs : List a) ->
(counter : List a) -> Split (head :: xs)
splitHelp head [] counter = SplitOne _
splitHelp head (x :: xs) [] = SplitPair head [] x xs
splitHelp head (x :: xs) [y] = SplitPair head [] x xs
splitHelp head (x :: xs) (_ :: _ :: ys)
= case splitHelp head xs ys of
SplitOne x => SplitPair x [] _ []
SplitPair x' xs y' ys => SplitPair x' (x :: xs) y' ys
||| Covering function for the `Split` view
||| Constructs the view in linear time
export
split : (xs : List a) -> Split xs
split [] = SplitNil
split (x :: xs) = splitHelp x xs xs
public export
data SplitRec : List a -> Type where
SplitRecNil : SplitRec []
SplitRecOne : (x : a) -> SplitRec [x]
SplitRecPair : (lefts, rights : List a) -> -- Explicit, don't erase
(lrec : Lazy (SplitRec lefts)) ->
(rrec : Lazy (SplitRec rights)) -> SplitRec (lefts ++ rights)
||| Covering function for the `SplitRec` view
||| Constructs the view in O(n lg n)
public export
splitRec : (xs : List a) -> SplitRec xs
splitRec xs with (sizeAccessible xs)
splitRec xs | acc with (split xs)
splitRec [] | acc | SplitNil = SplitRecNil
splitRec [x] | acc | SplitOne x = SplitRecOne x
splitRec (y :: ys ++ z :: zs) | Access acc | SplitPair y ys z zs
= SplitRecPair _ _
(splitRec (y :: ys) | acc _ (smallerLeft ys z zs))
(splitRec (z :: zs) | acc _ (smallerRight ys zs))
||| View for traversing a list backwards
public export
data SnocList : List a -> Type where
Empty : SnocList []
Snoc : (x : a) -> (xs : List a) ->
(rec : SnocList xs) -> SnocList (xs ++ [x])
snocListHelp : {input : _} ->
SnocList input -> (rest : List a) -> SnocList (input ++ rest)
snocListHelp snoc [] = rewrite appendNilRightNeutral input in snoc
snocListHelp snoc (x :: xs)
= rewrite appendAssociative input [x] xs in
snocListHelp (Snoc x input snoc) xs
||| Covering function for the `SnocList` view
||| Constructs the view in linear time
export
snocList : (xs : List a) -> SnocList xs
snocList xs = snocListHelp Empty xs