mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-20 10:02:03 +03:00
75032a7164
* Emit warning for fixities with no export modifiers This is to help update all the existing code to program with explicit fixity export directives in preparation for the behavioral change where they will become private by default.
214 lines
5.6 KiB
Idris
214 lines
5.6 KiB
Idris
||| General purpose two-end finite sequences,
|
|
||| with length in its type.
|
|
|||
|
|
||| This is implemented by finger tree.
|
|
module Data.Seq.Sized
|
|
|
|
import Control.WellFounded
|
|
|
|
import public Data.Fin
|
|
import public Data.Nat
|
|
import public Data.Vect
|
|
import public Data.Zippable
|
|
|
|
import Data.Seq.Internal
|
|
|
|
%default total
|
|
|
|
err : String -> a
|
|
err s = assert_total (idris_crash s)
|
|
|
|
||| A two-end finite sequences, with length in its type.
|
|
export
|
|
data Seq : Nat -> Type -> Type where
|
|
MkSeq : FingerTree (Elem e) -> Seq n e
|
|
|
|
||| O(1). The empty sequence.
|
|
export
|
|
empty : Seq 0 e
|
|
empty = MkSeq Empty
|
|
|
|
||| O(1). A singleton sequence.
|
|
export
|
|
singleton : e -> Seq 1 e
|
|
singleton a = MkSeq (Single (MkElem a))
|
|
|
|
||| O(n). A sequence of length n with a the value of every element.
|
|
export
|
|
replicate : (n : Nat) -> (a : e) -> Seq n e
|
|
replicate n a = MkSeq (replicate' n a)
|
|
|
|
||| O(1). The number of elements in the sequence.
|
|
export
|
|
length : {n : Nat} -> Seq n a -> Nat
|
|
length _ = n
|
|
|
|
||| O(n). Reverse the sequence.
|
|
export
|
|
reverse : Seq n a -> Seq n a
|
|
reverse (MkSeq tr) = MkSeq (reverseTree id tr)
|
|
|
|
export infixr 5 `cons`
|
|
||| O(1). Add an element to the left end of a sequence.
|
|
export
|
|
cons : e -> Seq n e -> Seq (S n) e
|
|
a `cons` MkSeq tr = MkSeq (MkElem a `consTree` tr)
|
|
|
|
export infixl 5 `snoc`
|
|
||| O(1). Add an element to the right end of a sequence.
|
|
export
|
|
snoc : Seq n e -> e -> Seq (S n) e
|
|
MkSeq tr `snoc` a = MkSeq (tr `snocTree` MkElem a)
|
|
|
|
||| O(log(min(m, n))). Concatenate two sequences.
|
|
export
|
|
(++) : Seq m e -> Seq n e -> Seq (m + n) e
|
|
MkSeq t1 ++ MkSeq t2 = MkSeq (addTree0 t1 t2)
|
|
|
|
||| O(1). View from the left of the sequence.
|
|
export
|
|
viewl : Seq (S n) a -> (a, Seq n a)
|
|
viewl (MkSeq tr) = case viewLTree tr of
|
|
Just (MkElem a, tr') => (a, MkSeq tr')
|
|
Nothing => err "viewl"
|
|
|
|
||| O(1). The first element of the sequence.
|
|
export
|
|
head : Seq (S n) a -> a
|
|
head = fst . viewl
|
|
|
|
||| O(1). The elements after the head of the sequence.
|
|
export
|
|
tail : Seq (S n) a -> Seq n a
|
|
tail = snd . viewl
|
|
|
|
||| O(1). View from the right of the sequence.
|
|
export
|
|
viewr : Seq (S n) a -> (Seq n a, a)
|
|
viewr (MkSeq tr) = case viewRTree tr of
|
|
Just (tr', MkElem a) => (MkSeq tr', a)
|
|
Nothing => err "viewr"
|
|
|
|
||| O(1). The elements before the last element of the sequence.
|
|
export
|
|
init : Seq (S n) a -> Seq n a
|
|
init = fst . viewr
|
|
|
|
||| O(1). The last element of the sequence.
|
|
export
|
|
last : Seq (S n) a -> a
|
|
last = snd . viewr
|
|
|
|
||| O(n). Turn a vector into a sequence.
|
|
export
|
|
fromVect : Vect n a -> Seq n a
|
|
fromVect xs = MkSeq (foldr (\x, t => MkElem x `consTree` t) Empty xs)
|
|
|
|
||| O(n). Turn a list into a sequence.
|
|
export
|
|
fromList : (xs : List a) -> Seq (length xs) a
|
|
fromList xs = fromVect (Vect.fromList xs)
|
|
|
|
||| O(n). Turn a sequence into a vector.
|
|
export
|
|
toVect : {n :Nat} -> Seq n a -> Vect n a
|
|
toVect _ {n = 0} = []
|
|
toVect ft {n = S _} =
|
|
let (x, ft') = viewl ft
|
|
in x :: toVect ft'
|
|
|
|
||| O(log(min(i, n-i))). The element at the specified position.
|
|
export
|
|
index : (i : Nat) -> (t : Seq n a) -> {auto ok : LT i n} -> a
|
|
index i (MkSeq t) = let (_, MkElem a) = lookupTree i t in a
|
|
|
|
||| O(log(min(i, n-i))). The element at the specified position.
|
|
||| Use Fin n to index instead.
|
|
export
|
|
index' : (t : Seq n a) -> (i : Fin n) -> a
|
|
index' (MkSeq t) fn = let (_, MkElem a) = lookupTree (finToNat fn) t in a
|
|
|
|
||| O(log(min(i, n-i))). Update the element at the specified position.
|
|
export
|
|
adjust : (f : a -> a) -> (i : Nat) -> (t : Seq n a) -> {auto ok : LT i n} -> Seq n a
|
|
adjust f i (MkSeq t) = MkSeq $ adjustTree (const (map f)) i t
|
|
|
|
||| O(log(min(i, n-i))). Replace the element at the specified position.
|
|
export
|
|
update : (i : Nat) -> a -> (t : Seq n a) -> {auto ok : LT i n} -> Seq n a
|
|
update i a t = adjust (const a) i t
|
|
|
|
||| O(log(min(i, n-i))). Split a sequence at a given position.
|
|
export
|
|
splitAt : (i : Nat) -> Seq (i + j) a -> (Seq i a, Seq j a)
|
|
splitAt i (MkSeq xs) =
|
|
let (l, r) = split i xs
|
|
in (MkSeq l, MkSeq r)
|
|
|
|
||| O(log(min(i, n-i))). The first i elements of a sequence.
|
|
export
|
|
take : (i : Nat) -> Seq (i + j) a -> Seq i a
|
|
take i seq = fst (splitAt i seq)
|
|
|
|
||| O(log(min(i, n-i))). Elements of a sequence after the first i.
|
|
export
|
|
drop : (i : Nat) -> Seq (i + j) a -> Seq j a
|
|
drop i seq = snd (splitAt i seq)
|
|
|
|
||| Dump the internal structure of the finger tree.
|
|
export
|
|
show' : Show a => Seq n a -> String
|
|
show' (MkSeq tr) = showPrec Open tr
|
|
|
|
public export
|
|
implementation Eq a => Eq (Seq n a) where
|
|
MkSeq x == MkSeq y = x == y
|
|
|
|
public export
|
|
implementation Ord a => Ord (Seq n a) where
|
|
compare (MkSeq x) (MkSeq y) = compare x y
|
|
|
|
public export
|
|
implementation Functor (Seq n) where
|
|
map f (MkSeq tr) = MkSeq (map (map f) tr)
|
|
|
|
public export
|
|
implementation Foldable (Seq n) where
|
|
foldr f z (MkSeq tr) = foldr (f . unElem) z tr
|
|
|
|
foldl f z (MkSeq tr) = foldl (\acc, (MkElem elem) => f acc elem) z tr
|
|
|
|
toList (MkSeq tr) = toList' tr
|
|
|
|
null (MkSeq Empty) = True
|
|
null _ = False
|
|
|
|
public export
|
|
implementation Traversable (Seq n) where
|
|
traverse f (MkSeq tr) = MkSeq <$> traverse (map MkElem . f . unElem) tr
|
|
|
|
public export
|
|
implementation Show a => Show (Seq n a) where
|
|
showPrec p = showPrec p . toList
|
|
|
|
public export
|
|
implementation Zippable (Seq n) where
|
|
zipWith f (MkSeq x) (MkSeq y) = MkSeq (zipWith' f x y)
|
|
|
|
zipWith3 f (MkSeq x) (MkSeq y) (MkSeq z) = MkSeq (zipWith3' f x y z)
|
|
|
|
unzipWith f (MkSeq zs) = let (xs, ys) = unzipWith' f zs in (MkSeq xs, MkSeq ys)
|
|
|
|
unzipWith3 f (MkSeq ws) = let (xs, ys, zs) = unzipWith3' f ws in (MkSeq xs, MkSeq ys, MkSeq zs)
|
|
|
|
||| This implementation works like a ZipList,
|
|
||| and is differnt from that of Seq.Unsized.
|
|
public export
|
|
implementation {n : Nat} -> Applicative (Seq n) where
|
|
pure = replicate n
|
|
(<*>) = zipWith ($)
|
|
|
|
public export
|
|
implementation Sized (Seq n a) where
|
|
size (MkSeq s) = size s
|