module Data.List.Base where
The type of listsπ
This module contains the definition of the type of lists, and some
basic operations on lists. Properties of these operations are in the
module Data.List
, not
here.
private variable
: Level
β : Type β
A B
infixr 20 _β·_
data List {β} (A : Type β) : Type β where
: List A
[] _β·_ : A β List A β List A
{-# BUILTIN LIST List #-}
One of the first things we set up is list literal syntax (the From-product
class) for lists. The list
corresponding to an n-ary product is the list of its elements.
instance
: From-product A (Ξ» _ β List A)
From-prod-List .From-product.from-prod = go where
From-prod-List : β n β Vecβ A n β List A
go = []
go zero xs (suc zero) xs = xs β· []
go (suc (suc n)) (x , xs) = x β· go (suc n) xs
go
-- Test:
_ : Path (List Nat) [ 1 , 2 , 3 ] (1 β· 2 β· 3 β· [])
_ = refl
βFieldsβπ
: A β List A β A
head = def
head def [] _ (x β· _) = x
head
: List A β List A
tail = []
tail [] (_ β· xs) = xs tail
Eliminationπ
As with any inductive type, the type of lists-of-As has a canonically-defined eliminator, but it also has some fairly popular recursors, called βfoldsβ:
List-elim: β {β β'} {A : Type β} (P : List A β Type β')
β P []
β (β x xs β P xs β P (x β· xs))
β β x β P x
= p[]
List-elim P p[] pβ· [] (x β· xs) = pβ· x xs (List-elim P p[] pβ· xs) List-elim P p[] pβ·
instance
: Foldable (eff List)
Foldable-List .foldr f x = List-elim _ x (Ξ» x _ β f x)
Foldable-List
: Traversable (eff List)
Traversable-List = record { traverse = go } where
Traversable-List
go: β {M : Effect} β¦ _ : Idiom M β¦ (let module M = Effect M) {β β'}
{a : Type β} {b : Type β'}
β (a β M.β b) β List a β M.β (List b)
= pure []
go f [] (x β· xs) = β¦ f x β· go f xs β¦
go f
: (B β A β B) β B β List A β B
foldl = x
foldl f x [] (a β· as) = foldl f (f x a) as foldl f x
Functorial actionπ
Itβs also possible to lift a function A β B
to a
function List A β List B
.
instance
: Map (eff List)
Map-List = record { map = go } where
Map-List : (A β B) β List A β List B
go = []
go f [] (x β· xs) = f x β· go f xs go f
Monoidal structureπ
We can define concatenation of lists by recursion:
_++_ : β {β} {A : Type β} β List A β List A β List A
= ys
[] ++ ys (x β· xs) ++ ys = x β· (xs ++ ys)
infixr 8 _++_
instance
: β {β} {A : Type β} β Append (List A)
Append-List = record { mempty = [] ; _<>_ = _++_ } Append-List
: (Nat β A β B) β Nat β List A β List B
map-up _ [] = []
map-up f (x β· xs) = f n x β· map-up f (suc n) xs
map-up f n
: List A β Nat
length = zero
length [] (x β· xs) = suc (length xs)
length
: List (List A) β List A
concat = []
concat [] (x β· xs) = x ++ concat xs
concat
: Nat β List Nat
count = []
count zero (suc n) = 0 β· map suc (count n)
count
: List Nat β Nat
product = 1
product [] (x β· xs) = x * product xs
product
: List A β List A
reverse {A = A} = go [] module reverse where
reverse : List A β List A β List A
go = acc
go acc [] (x β· xs) = go (x β· acc) xs
go acc
_β·r_ : List A β A β List A
= xs ++ (x β· [])
xs β·r x
infixl 20 _β·r_
: (A β A β Bool) β List A β List A β Bool
all=? = true
all=? eq=? [] [] (x β· ys) = false
all=? eq=? [] (x β· xs) [] = false
all=? eq=? (x β· xs) (y β· ys) = and (eq=? x y) (all=? eq=? xs ys)
all=? eq=?
: β {β} {A : Type β} β List A β List (Nat Γ A)
enumerate = go 0 where
enumerate : Nat β List _ β List (Nat Γ _)
go = []
go x [] (a β· b) = (x , a) β· go (suc x) b
go x
: β {β} {A : Type β} β Nat β List A β List A
take 0 xs = []
take (suc n) [] = []
take (suc n) (x β· xs) = x β· take n xs
take
: β {β} {A : Type β} β Nat β List A β List A
drop = xs
drop zero xs (suc n) [] = []
drop (suc n) (x β· xs) = drop n xs
drop
: β {β} {A : Type β} β Nat β List A β List A Γ List A
split-at 0 xs = [] , xs
split-at (suc n) [] = [] , []
split-at (suc n) (x β· xs) = Γ-mapβ (x β·_) (split-at n xs)
split-at
: β {β} {A : Type β} (p : A β Bool) β List A β List A Γ List A
span = [] , []
span p [] (x β· xs) with p x
span p ... | true = Γ-mapβ (x β·_) (span p xs)
... | false = [] , x β· xs
: β {β} {A : Type β} (p : A β Bool) β List A β List A
filter = []
filter p [] (x β· xs) with p x
filter p ... | true = x β· filter p xs
... | false = filter p xs
: β {β} {A : Type β} (x : A) (xs : List A) β List A
intercalate = []
intercalate x [] (y β· []) = y β· []
intercalate x (y β· z β· xs) = y β· x β· intercalate x (z β· xs)
intercalate x
: β {β β'} {A : Type β} {B : Type β'} β List A β List B β List (A Γ B)
zip _ = []
zip [] _ [] = []
zip (a β· as) (b β· bs) = (a , b) β· zip as bs
zip
: β {β β'} {A : Type β} {B : Type β'} β List (A Γ B) β List A Γ List B
unzip = [] , []
unzip [] ((a , b) β· xs) = Γ-map (a β·_) (b β·_) (unzip xs)
unzip
instance
: Idiom (eff List)
Idiom-List .pure a = a β· []
Idiom-List ._<*>_ f a = concat ((_<$> a) <$> f)
Idiom-List
: Bind (eff List)
Bind-List ._>>=_ a f = concat (f <$> a)
Bind-List
: Alt (eff List)
Alt-List .Alt.fail = []
Alt-List .Alt._<|>_ = _<>_ Alt-List
Predicatesπ
We can define a function that determines if a boolean-valued predicate holds on every element of a list.
: β {β} {A : Type β} β (A β Bool) β List A β Bool
all-of = true
all-of f [] (x β· xs) = and (f x) (all-of f xs) all-of f
Dually, we can also define a function that determines if a boolean-valued predicate holds on some element of a list.
: β {β} {A : Type β} β (A β Bool) β List A β Bool
any-of = false
any-of f [] (x β· xs) = or (f x) (any-of f xs) any-of f
: β {x y : A} {xs ys} β (x β· xs) β‘ (y β· ys) β x β‘ y
β·-head-inj {x = x} p = ap (head x) p
β·-head-inj
: β {x y : A} {xs ys} β (x β· xs) β‘ (y β· ys) β xs β‘ ys
β·-tail-inj = ap tail p
β·-tail-inj p
: β {x : A} {xs} β Β¬ (x β· xs) β‘ []
β·β [] {A = A} p = subst distinguish p tt where
β·β [] : List A β Type
distinguish = β₯
distinguish [] (_ β· _) = β€
distinguish
instance
: β β¦ d : Discrete A β¦ β Discrete (List A)
Discrete-List {x = []} {y = []} = yes refl
Discrete-List {x = []} {y = x β· y} = no Ξ» p β β·β [] (sym p)
Discrete-List {x = x β· xs} {y = []} = no β·β []
Discrete-List {x = x β· xs} {y = y β· ys} = case x β‘? y of Ξ» where
Discrete-List (yes x=y) β case Discrete-List {x = xs} {ys} of Ξ» where
(yes xs=ys) β yes (apβ _β·_ x=y xs=ys)
(no xsβ ys) β no Ξ» p β xsβ ys (β·-tail-inj p)
(no xβ y) β no Ξ» p β xβ y (β·-head-inj p)
traverse-up: β {M : Effect} β¦ _ : Idiom M β¦ (let module M = Effect M) {β β'}
{a : Type β} {b : Type β'}
β (Nat β a β M.β b) β Nat β List a β M.β (List b)
= sequence (map-up f n xs)
traverse-up f n xs
: β¦ _ : Discrete A β¦ β A β List (A Γ B) β Maybe B
lookup = nothing
lookup x [] ((k , v) β· xs) with x β‘? k
lookup x ... | yes _ = just v
... | no _ = lookup x xs
_!_ : (l : List A) β Fin (length l) β A
(x β· xs) ! n with fin-view n
... | zero = x
... | suc i = xs ! i
: β {n} (f : Fin n β A) β List A
tabulate {n = zero} f = []
tabulate {n = suc n} f = f fzero β· tabulate (f β fsuc) tabulate