{-# OPTIONS --safe #-}

module Data.List.Properties where

open import Prelude
open import Algebra
open import Data.List

foldr-universal :  (h : List B  A) f e
                 (h []  e)
                 (∀ x xs  h (x  xs)  f x (h xs))
                  xs  h xs  foldr f e xs
foldr-universal h f e base step [] = base
foldr-universal h f e base step (x  xs) =
  step x xs ; cong (f x) (foldr-universal h f e base step xs)

foldr-id : (xs : List A)  xs  foldr _∷_ [] xs
foldr-id = foldr-universal id _∷_ [] refl  _ _  refl)

foldr-fusion :  (f : C  A) {_⊕_ : B  C  C} {_⊗_ : B  A  A} e
               (∀ x y  f (x  y)  x  f y)
                xs  f (foldr _⊕_ e xs)  foldr _⊗_ (f e) xs
foldr-fusion h {f} {g} e fuse =
  foldr-universal (h  foldr f e) g (h e) refl  x xs  fuse x (foldr f e xs))

lmap : (A  B)  List A  List B
lmap f = foldr (_∷_  f) []

functorList : Functor {ℓ₁ = a} List
functorList .Functor.map = lmap
functorList .Functor.map-id = sym ∘′ foldr-id
functorList .Functor.map-comp f g = foldr-fusion (lmap f) [] λ x y  refl

all : (A  Bool)  List A  Bool
all p = foldr (_&&_  p) true

infixr 5 _∈_ _∉_

_∈_ : A  List A  Type _
x  xs =  i × (xs !! i  x)

_∉_ : A  List A  Type _
x  xs = ¬ (x  xs)

there :  (y : A) {x} {xs : List A}  x  xs  x  y  xs
there _ (i , p) = fsuc i , p