{-# OPTIONS --without-K --safe #-}
{-# OPTIONS --without-K --safe #-}
module Data.Nat.Table where
open import Data.Nat as ℕ using (ℕ; suc; zero)
open import Data.List as List using (List; _∷_; [])
open import Function
Table : Set
Table = List ℕ
para : ∀ {a b} {A : Set a} {B : Set b} → (A → List A → B → B) → B → List A → B
para f b [] = b
para f b (x ∷ xs) = f x xs (para f b xs)
insert : ℕ → Table → Table
insert x xs = para (go zero) (_∷ []) xs x
where
go : ℕ → ℕ → Table → (ℕ → Table) → ℕ → Table
go k zero xs g zero = k ∷ xs
go k zero xs g (suc i) = k ∷ g i
go k (suc x) xs g zero = k ∷ x ∷ xs
go k (suc x) xs g (suc i) = go (suc k) x xs g i
open import Data.Maybe as Maybe using (Maybe; just; nothing)
member : ℕ → Table → Maybe ℕ
member x xs = List.foldr go (const (const nothing)) xs x 0
where
go : ℕ → (ℕ → ℕ → Maybe ℕ) → ℕ → ℕ → Maybe ℕ
go zero ys zero k = just k
go zero ys (suc x) k = ys x (suc k)
go (suc y) ys zero _ = nothing
go (suc y) ys (suc x) k = go y ys x k
fromList : List ℕ → Table
fromList = List.foldr insert []
toList : Table → List ℕ
toList = tail′ ∘ List.map ℕ.pred ∘ List.scanl (λ x y → suc (y ℕ.+ x)) 0
where
tail′ : List ℕ → List ℕ
tail′ [] = []
tail′ (_ ∷ xs) = xs
private
open import Relation.Binary.PropositionalEquality
example₁ : fromList (4 ∷ 3 ∷ 1 ∷ 0 ∷ 2 ∷ []) ≡ (0 ∷ 0 ∷ 0 ∷ 0 ∷ 0 ∷ [])
example₁ = refl
example₂ : member 3 (fromList (4 ∷ 3 ∷ 1 ∷ 0 ∷ 2 ∷ [])) ≡ just 3
example₂ = refl
example₃ : toList (fromList (4 ∷ 3 ∷ 1 ∷ 0 ∷ 2 ∷ [])) ≡ (0 ∷ 1 ∷ 2 ∷ 3 ∷ 4 ∷ [])
example₃ = refl