{-# OPTIONS --without-K --safe #-}
module Data.SnocList.Base where
open import Algebra.Bundles.Raw using (RawMagma; RawMonoid)
open import Data.Bool.Base as Bool using (Bool; true; false; if_then_else_)
open import Data.Fin.Base using (Fin; zero; suc)
open import Data.Maybe.Base as Maybe using (Maybe; nothing; just; maybe′)
open import Data.Nat.Base as ℕ using (ℕ; zero; suc)
open import Data.Product.Base as Product using (_×_; _,_)
open import Data.Sum.Base as Sum using (_⊎_)
open import Data.These.Base as These using (These; this; that; these)
open import Function.Base using (id; _∘_; _∘′_; _∘₂_; flip; _$′_; const)
open import Level using (Level)
open import Relation.Unary as U using (Pred)
open import Relation.Binary.Core using (Rel)
import Relation.Binary.Definitions as B
open import Relation.Binary.PropositionalEquality.Core using (_≡_; refl)
open import Relation.Nullary.Decidable.Core using (does; T?; ¬?)
private
variable
a b c p ℓ : Level
A : Set a
B : Set b
C : Set c
open import Data.List.Base as List>
using ([])
renaming ( List to List>
; _∷_ to _:>_
)
public
infixl 5 _<:_
data List< (A : Set a) : Set a where
[] : List< A
_<:_ : List< A → A → List< A
infixl 5 _<><_
_<><_ : List< A → List> A → List< A
sx <>< [] = sx
sx <>< (x :> xs) = (sx <: x) <>< xs
infixr 6 _<>>_
_<>>_ : List< A → List> A → List> A
[] <>> xs = xs
(sx <: x) <>> xs = sx <>> (x :> xs)
private
[<1,2] : List< ℕ
[<1,2] = [] <: 1 <: 2
[>3,4] : List> ℕ
[>3,4] = 3 :> 4 :> []
[<1,2,3,4] : List< ℕ
[<1,2,3,4] = [] <: 1 <: 2 <: 3 <: 4
[>1,2,3,4] : List> ℕ
[>1,2,3,4] = 1 :> 2 :> 3 :> 4 :> []
_ : [<1,2] <>< [>3,4] ≡ [<1,2,3,4]
_ = refl
_ : [<1,2] <>> [>3,4] ≡ [>1,2,3,4]
_ = refl
toList> : List< A → List> A
toList> = _<>> []
fromList> : List> A → List< A
fromList> = [] <><_
map : (A → B) → List< A → List< B
map f [] = []
map f (sx <: x) = map f sx <: f x
infixl 5 _++_
_++_ : List< A → List< A → List< A
sx ++ [] = sx
sx ++ (sy <: x) = (sx ++ sy) <: x
intersperse : A → List< A → List< A
intersperse x [] = []
intersperse x sx@([] <: _) = sx
intersperse x (sy <: y) = intersperse x sy <: x <: y
intercalate : List< A → List< (List< A) → List< A
intercalate sx [] = []
intercalate sx ([] <: sy) = sy
intercalate sx (sys <: sy) = intercalate sx sys ++ sx ++ sy
cartesianProductWith : (A → B → C) → List< A → List< B → List< C
cartesianProductWith f [] _ = []
cartesianProductWith f (sx <: x) sy = cartesianProductWith f sx sy ++ map (f x) sy
cartesianProduct : List< A → List< B → List< (A × B)
cartesianProduct = cartesianProductWith _,_
alignWith : (These A B → C) → List< A → List< B → List< C
alignWith f [] bs = map (f ∘′ that) bs
alignWith f as [] = map (f ∘′ this) as
alignWith f (as <: a) (bs <: b) = alignWith f as bs <: f (these a b)
zipWith : (A → B → C) → List< A → List< B → List< C
zipWith f (sx <: x) (sy <: y) = zipWith f sx sy <: f x y
zipWith f _ _ = []
unalignWith : (A → These B C) → List< A → List< B × List< C
unalignWith f [] = [] , []
unalignWith f (as <: a) with f a
... | this b = Product.map₁ (_<: b) (unalignWith f as)
... | that c = Product.map₂ (_<: c) (unalignWith f as)
... | these b c = Product.map (_<: b) (_<: c) (unalignWith f as)
unzipWith : (A → B × C) → List< A → List< B × List< C
unzipWith f [] = [] , []
unzipWith f (xsy <: xy) = Product.zip _<:_ _<:_ (unzipWith f xsy) (f xy)
partitionSumsWith : (A → B ⊎ C) → List< A → List< B × List< C
partitionSumsWith f = unalignWith (These.fromSum ∘′ f)
align : List< A → List< B → List< (These A B)
align = alignWith id
zip : List< A → List< B → List< (A × B)
zip = zipWith (_,_)
unalign : List< (These A B) → List< A × List< B
unalign = unalignWith id
unzip : List< (A × B) → List< A × List< B
unzip = unzipWith id
partitionSums : List< (A ⊎ B) → List< A × List< B
partitionSums = partitionSumsWith id
merge : {R : Rel A ℓ} → B.Decidable R → List< A → List< A → List< A
merge R? [] sy = sy
merge R? sx [] = sx
merge R? sxx@(sx <: x) syy@(sy <: y) = if does (R? x y)
then merge R? sx syy <: x
else merge R? sxx sy <: y
foldr : (A → B → B) → B → List< A → B
foldr c n [] = n
foldr c n (sx <: x) = foldr c (c x n) sx
foldl : (A → B → A) → A → List< B → A
foldl c n [] = n
foldl c n (sx <: x) = c (foldl c n sx) x
concat : List< (List< A) → List< A
concat = foldl _++_ []
_ : concat ([] <: [<1,2] <: (fromList> [>3,4])) ≡ [<1,2,3,4]
_ = refl
concatMap : (A → List< B) → List< A → List< B
concatMap f = concat ∘′ map f
_ : (concatMap (λ n → [] <: n <: suc n) [<1,2,3,4]) <>> []
≡ List>.concatMap (λ n → n :> suc n :> []) ([<1,2,3,4] <>> [])
_ = refl
ap : List< (A → B) → List< A → List< B
ap fs as = concatMap (flip map as) fs
catMaybes : List< (Maybe A) → List< A
catMaybes = foldl (flip $′ maybe′ (flip _<:_) id) []
_ : let trash = [] <: nothing in
catMaybes (trash ++ map just [<1,2,3,4] ++ trash) ≡ [<1,2,3,4]
_ = refl
mapMaybe : (A → Maybe B) → List< A → List< B
mapMaybe p = catMaybes ∘′ map p
null : List< A → Bool
null [] = true
null (_ <: _) = false
length : List< A → ℕ
length = foldl (flip $′ const suc) 0
fromMaybe : Maybe A → List< A
fromMaybe (just x) = [] <: x
fromMaybe nothing = []
replicate : ℕ → A → List< A
replicate zero x = []
replicate (suc n) x = replicate n x <: x
iterate : (A → A) → A → ℕ → List< A
iterate f e zero = []
iterate f e (suc n) = iterate f (f e) n <: e
inits : List< A → List< (List< A)
inits {A = A} sx = tail sx <: []
module Inits where
tail : List< A → List< (List< A)
tail [] = []
tail (sx <: x) = map (_<: x) (tail sx) <: ([] <: x)
tails : List< A → List< (List< A)
tails {A = A} sx = tail sx <: sx
module Tails where
tail : List< A → List< (List< A)
tail [] = []
tail (sx <: _) = tail sx <: sx
insertAt : (sx : List< A) → Fin (suc (length sx)) → A → List< A
insertAt sx zero v = sx <: v
insertAt (sx <: x) (suc i) v = insertAt sx i v <: x
updateAt : (sx : List< A) → Fin (length sx) → (A → A) → List< A
updateAt (sx <: x) zero f = sx <: f x
updateAt (sx <: x) (suc i) f = updateAt sx i f <: x
lookup : ∀ (sx : List< A) → Fin (length sx) → A
lookup (sx <: x) zero = x
lookup (sx <: x) (suc i) = lookup sx i
applyUpTo : (ℕ → A) → ℕ → List< A
applyUpTo f zero = []
applyUpTo f (suc n) = applyUpTo (f ∘′ suc) n <: f zero
applyDownFrom : (ℕ → A) → ℕ → List< A
applyDownFrom f zero = []
applyDownFrom f (suc n) = applyDownFrom f n <: f n
tabulate : ∀ {n} (f : Fin n → A) → List< A
tabulate {n = zero} f = []
tabulate {n = suc n} f = tabulate (f ∘′ suc) <: f zero
upTo : ℕ → List< ℕ
upTo = applyUpTo id
downFrom : ℕ → List< ℕ
downFrom = applyDownFrom id
allFin : ∀ n → List< (Fin n)
allFin n = tabulate id
unfold : ∀ (P : ℕ → Set b)
(f : ∀ {n} → P (suc n) → Maybe (A × P n)) →
∀ {n} → P n → List< A
unfold P f {n = zero} s = []
unfold P f {n = suc n} s = maybe′ (λ (x , s′) → unfold P f s′ <: x) [] (f s)
reverseAcc : List< A → List< A → List< A
reverseAcc = foldr (flip _<:_)
reverse : List< A → List< A
reverse = reverseAcc []
_ : toList> (reverse [<1,2,3,4]) ≡ List>.reverse (toList> [<1,2,3,4])
_ = refl
infixr 5 _++ʳ_
_++ʳ_ : List< A → List< A → List< A
_++ʳ_ = reverseAcc
_ : let [<3,4] = fromList> [>3,4] in
[<1,2] ++ʳ [<3,4] ≡ [<1,2] ++ reverse [<3,4]
_ = refl
infixr 6 _ˡ∷_
_ˡ∷_ : A → List< A → List< A
x ˡ∷ sx = ([] <: x) ++ sx
infixr 5 _ˡ∷′_
data InitLast {A : Set a} : List< A → Set a where
[] : InitLast []
_ˡ∷′_ : (x : A) (sx : List< A) → InitLast (x ˡ∷ sx)
initLast : (sx : List< A) → InitLast sx
initLast [] = []
initLast (sx <: x) with initLast sx
... | [] = x ˡ∷′ []
... | y ˡ∷′ sy = y ˡ∷′ (sy <: x)
uncons : List< A → Maybe (A × List< A)
uncons as with initLast as
... | [] = nothing
... | x ˡ∷′ sx = just (x , sx)
unsnoc : List< A → Maybe (List< A × A)
unsnoc [] = nothing
unsnoc (sx <: x) = just (sx , x)
head : List< A → Maybe A
head [] = nothing
head (_ <: x) = just x
tail : List< A → Maybe (List< A)
tail [] = nothing
tail (sx <: _) = just sx
last : List< A → Maybe A
last [] = nothing
last ([] <: x) = just x
last (sx <: _) = last sx
take : ℕ → List< A → List< A
take zero sx = []
take (suc n) [] = []
take (suc n) (sx <: x) = take n sx <: x
drop : ℕ → List< A → List< A
drop zero sx = sx
drop (suc n) [] = []
drop (suc n) (sx <: x) = drop n sx
splitAt : ℕ → List< A → List< A × List< A
splitAt zero sx = (sx , [])
splitAt (suc n) [] = ([] , [])
splitAt (suc n) (sx <: x) = Product.map₂ (_<: x) (splitAt n sx)
removeAt : (sx : List< A) → Fin (length sx) → List< A
removeAt (sx <: _) zero = sx
removeAt (sx <: x) (suc i) = removeAt sx i <: x
takeWhile : ∀ {P : Pred A p} → U.Decidable P → List< A → List< A
takeWhile P? [] = []
takeWhile P? (sx <: x) =
if does (P? x) then takeWhile P? sx <: x else []
takeWhileᵇ : (A → Bool) → List< A → List< A
takeWhileᵇ p = takeWhile (T? ∘ p)
dropWhile : ∀ {P : Pred A p} → U.Decidable P → List< A → List< A
dropWhile P? [] = []
dropWhile P? sxx@(sx <: x) =
if does (P? x) then dropWhile P? sx else sxx
dropWhileᵇ : (A → Bool) → List< A → List< A
dropWhileᵇ p = dropWhile (T? ∘ p)
filter : ∀ {P : Pred A p} → U.Decidable P → List< A → List< A
filter P? [] = []
filter P? (sx <: x) =
let ih = filter P? sx in
if does (P? x) then ih <: x else ih
filterᵇ : (A → Bool) → List< A → List< A
filterᵇ p = filter (T? ∘ p)
partition : ∀ {P : Pred A p} → U.Decidable P → List< A → (List< A × List< A)
partition P? [] = ([] , [])
partition P? (sx <: x) with does (P? x) | partition P? sx
... | true | (sy , sz) = (sy <: x , sz)
... | false | (sy , sz) = (sy , sz <: x)
partitionᵇ : (A → Bool) → List< A → List< A × List< A
partitionᵇ p = partition (T? ∘ p)
span : ∀ {P : Pred A p} → U.Decidable P → List< A → (List< A × List< A)
span P? [] = ([] , [])
span P? sxx@(sx <: x) with does (P? x)
... | true = Product.map₂ (_<: x) (span P? sx)
... | false = (sxx , [])
spanᵇ : (A → Bool) → List< A → List< A × List< A
spanᵇ p = span (T? ∘ p)
break : ∀ {P : Pred A p} → U.Decidable P → List< A → (List< A × List< A)
break P? = span (¬? ∘ P?)
breakᵇ : (A → Bool) → List< A → List< A × List< A
breakᵇ p = break (T? ∘ p)
linesBy : ∀ {P : Pred A p} → U.Decidable P → List< A → List< (List< A)
linesBy {A = A} P? cs = go cs [] where
go : List< A → List> A → List< (List< A)
go [] l = [] <: fromList> l
go (cs <: c) l = if does (P? c)
then go cs [] <: fromList> l
else go cs (c :> l)
linesByᵇ : (A → Bool) → List< A → List< (List< A)
linesByᵇ p = linesBy (T? ∘ p)
_ : linesByᵇ (ℕ._≤ᵇ 0) ([] <: 0 <: 1 <: 2 <: 0 <: 3 <: 0 <: 0 <: 4) ≡
[] <: [] <: ([] <: 1 <: 2) <: ([] <: 3) <: [] <: ([] <: 4)
_ = refl
_ : linesByᵇ (ℕ._≤ᵇ 0) ([] <: 1 <: 2 <: 0 <: 3 <: 0 <: 0 <: 4) ≡
[] <: ([] <: 1 <: 2) <: ([] <: 3) <: [] <: ([] <: 4)
_ = refl
wordsBy : ∀ {P : Pred A p} → U.Decidable P → List< A → List< (List< A)
wordsBy {A = A} P? cs = go cs [] where
snoc : List< (List< A) → List> A → List< (List< A)
snoc sas [] = sas
snoc sas as = sas <: fromList> as
go : List< A → List> A → List< (List< A)
go [] w = snoc [] w
go (cs <: c) w = if does (P? c)
then snoc (go cs []) w
else go cs (c :> w)
wordsByᵇ : (A → Bool) → List< A → List< (List< A)
wordsByᵇ p = wordsBy (T? ∘ p)
derun : ∀ {R : Rel A p} → B.Decidable R → List< A → List< A
derun R? [] = []
derun R? sx@([] <: x) = sx
derun R? (sx@(_ <: y) <: x) with does (R? x y) | derun R? sx
... | true | sy = sy
... | false | sy = sy <: x
derunᵇ : (A → A → Bool) → List< A → List< A
derunᵇ r = derun (T? ∘₂ r)
deduplicate : ∀ {R : Rel A p} → B.Decidable R → List< A → List< A
deduplicate R? [] = []
deduplicate R? (sx <: x) = filter (¬? ∘ R? x) (deduplicate R? sx) <: x
deduplicateᵇ : (A → A → Bool) → List< A → List< A
deduplicateᵇ r = deduplicate (T? ∘₂ r)
find : ∀ {P : Pred A p} → U.Decidable P → List< A → Maybe A
find P? [] = nothing
find P? (sx <: x) = if does (P? x) then just x else find P? sx
findᵇ : (A → Bool) → List< A → Maybe A
findᵇ p = find (T? ∘ p)
findIndex : ∀ {P : Pred A p} → U.Decidable P → (sx : List< A) → Maybe (Fin (length sx))
findIndex P? [] = nothing
findIndex P? (sx <: x) = if does (P? x)
then just zero
else Maybe.map suc (findIndex P? sx)
findIndexᵇ : (A → Bool) → (sx : List< A) → Maybe (Fin (length sx))
findIndexᵇ p = findIndex (T? ∘ p)
findIndices : ∀ {P : Pred A p} → U.Decidable P → (sx : List< A) → List< (Fin (length sx))
findIndices P? [] = []
findIndices P? (sx <: x) = if does (P? x)
then indices <: zero
else indices
where indices = map suc (findIndices P? sx)
findIndicesᵇ : (A → Bool) → (sx : List< A) → List< (Fin (length sx))
findIndicesᵇ p = findIndices (T? ∘ p)
infixl 5 _[_]%=_ _[_]∷=_
_[_]%=_ : (sx : List< A) → Fin (length sx) → (A → A) → List< A
sx [ i ]%= f = updateAt sx i f
_[_]∷=_ : (sx : List< A) → Fin (length sx) → A → List< A
sx [ k ]∷= v = sx [ k ]%= const v
infixr 5 _<:?_
_<:?_ : List< A → Maybe A → List< A
sx <:? mx = maybe′ (sx <:_) sx mx
infixl 6 _?ˡ∷_
_?ˡ∷_ : Maybe A → List< A → List< A
mx ?ˡ∷ sx = maybe′ (_ˡ∷ sx) sx mx
module _ (A : Set a) where
++-rawMagma : RawMagma a _
++-rawMagma = record
{ Carrier = List< A
; _≈_ = _≡_
; _∙_ = _++_
}
++-[]-rawMonoid : RawMonoid a _
++-[]-rawMonoid = record
{ Carrier = List< A
; _≈_ = _≡_
; _∙_ = _++_
; ε = []
}