{-# OPTIONS --without-K --safe #-}

--------------------------------------------------------------------------------
-- Simple implementation of sets of ℕ.
--------------------------------------------------------------------------------

{-# 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