module Data.List.Properties where

open import Prelude

foldr-map-fusion :  {a b c} {A : Set a} {B : Set b} {C : Set c}
                     (f : B  C  C) (g : A  B) (z : C) (xs : List A) 
                     foldr f z (map g xs)  foldr (f  g) z xs
foldr-map-fusion f g z [] = refl
foldr-map-fusion f g z (x  xs)
  rewrite foldr-map-fusion f g z xs
        = refl

foldl-map-fusion :  {a b c} {A : Set a} {B : Set b} {C : Set c}
                     (f : C  B  C) (g : A  B) (z : C) (xs : List A) 
                     foldl f z (map g xs)  foldl  x y  f x (g y)) z xs
foldl-map-fusion f g z [] = refl
foldl-map-fusion f g z (x  xs)
  rewrite foldl-map-fusion f g (f z (g x)) xs
        = refl

foldl-assoc :  {a} {A : Set a} (f : A  A  A) 
                (∀ x y z  f x (f y z)  f (f x y) z) 
                 y z xs  foldl f (f y z) xs  f y (foldl f z xs)
foldl-assoc f assoc y z [] = refl
foldl-assoc f assoc y z (x  xs)
  rewrite sym (assoc y z x)
        = foldl-assoc f assoc y (f z x) xs

foldl-foldr :  {a} {A : Set a} (f : A  A  A) (z : A) 
                (∀ x y z  f x (f y z)  f (f x y) z) 
                (∀ x  f z x  x)  (∀ x  f x z  x) 
                 xs  foldl f z xs  foldr f z xs
foldl-foldr f z assoc idl idr [] = refl
foldl-foldr f z assoc idl idr (x  xs)
  rewrite sym (foldl-foldr f z assoc idl idr xs)
        | idl x ⟨≡⟩ʳ idr x
        = foldl-assoc f assoc x z xs