-- This is a self contained development of the proof that
-- foldr f z (reverse xs) ≡ foldl (flip f) z xs
-- I use some definitions from
-- http://code.haskell.org/~dolio/agda-play/
-- Particularly Data.List and Relation.Equivality
module Folding where
flip : forall {A B C} -> (A -> B -> C) -> B -> A -> C
flip f b a = f a b
infix 20 _≡_
infixr 30 _≡→_
infixr 25 _lhs_ _rhs_
data _≡_ {a : Set} : a -> a -> Set where
refl : forall {x} -> x ≡ x
≡sub : forall {a}{P : a -> Set}{x y : a} -> x ≡ y -> P x -> P y
≡sub refl Px = Px
≡symm : forall {a}{x y : a} -> x ≡ y -> y ≡ x
≡symm refl = refl
≡trans : forall {a}{x y z : a} -> x ≡ y -> y ≡ z -> x ≡ z
≡trans refl refl = refl
-- take and equation and apply a function to both sides
_≡→_ : forall {a b}{x y : a} -> x ≡ y -> (f : a -> b) -> f x ≡ f y
refl ≡→ _ = refl
-- rewrite on the left
_lhs_ : forall {a}{x y k : a} -> x ≡ k -> x ≡ y -> y ≡ k
E₁ lhs E₂ = ≡trans (≡symm E₂) E₁
-- rewrite on the right
_rhs_ : forall {a}{x y k : a} -> k ≡ x -> x ≡ y -> k ≡ y
E₁ rhs E₂ = ≡symm (≡symm E₁ lhs E₂)
infixr 50 _∷_
infixr 40 _++_
data [_] (a : Set) : Set where
[] : [ a ]
_∷_ : a -> [ a ] -> [ a ]
foldr : {a b : Set} -> (a -> b -> b) -> b -> [ a ] -> b
foldr _ z [] = z
foldr f z (a ∷ as) = f a (foldr f z as)
foldl : {a b : Set} -> (b -> a -> b) -> b -> [ a ] -> b
foldl _ z [] = z
foldl f z (a ∷ as) = foldl f (f z a) as
_++_ : forall {a} -> [ a ] -> [ a ] -> [ a ]
[] ++ ys = ys
(x ∷ xs) ++ ys = x ∷ (xs ++ ys)
reverse : {A : Set} -> [ A ] -> [ A ]
reverse [] = []
reverse (x ∷ xs) = reverse xs ++ (x ∷ [])
-- Some theorems about ++
-- [] is the right unit
++unit : forall {a} -> (x : [ a ]) -> x ++ [] ≡ x
++unit [] = refl
++unit (x ∷ xs) = ++unit xs ≡→ \s -> x ∷ s
-- Associative
++assoc : forall {a} -> (a b c : [ a ]) ->
(a ++ b) ++ c ≡ a ++ (b ++ c)
++assoc {_} [] _ _ = refl
++assoc {_} (x ∷ xs) _ _ = ++assoc xs _ _ ≡→ \s -> x ∷ s
++reverse : forall {a} (x y : [ a ]) ->
reverse y ++ reverse x ≡ reverse (x ++ y)
++reverse [] ys = ++unit (reverse ys)
++reverse (x ∷ xs) ys = ++reverse xs ys
≡→ (\s -> s ++ reverse (x ∷ []))
lhs ++assoc (reverse ys) _ _
++foldr : forall {a b} ->
(f : a -> b -> b) -> (z : b) -> (xs ys : [ a ]) ->
foldr f z (xs ++ ys) ≡ foldr f (foldr f z ys) xs
++foldr f z [] ys = refl
++foldr f z (x ∷ xs) ys = ++foldr f z xs ys ≡→ f x
-- This identity is not actually used but I leave it in for
-- the sake of completeness
++foldl : forall {a b} ->
(f : b -> a -> b) -> (z : b) -> (xs ys : [ a ]) ->
foldl f z (xs ++ ys) ≡ foldl f (foldl f z xs) ys
++foldl f z [] ys = refl
++foldl f z (x ∷ xs) ys = ++foldl f (f z x) xs ys
foldl^foldr : forall {a b} ->
(f : a -> b -> b) -> (z : b) -> (xs : [ a ]) ->
foldr f z (reverse xs) ≡ foldl (flip f) z xs
foldl^foldr f z [] = refl
foldl^foldr f z (x ∷ xs) = foldl^foldr f (f x z) xs
lhs ≡symm (++foldr f z
(reverse xs)
(x ∷ []))
Thursday, 14 February 2008
Proof of the foldl, foldr relation
Subscribe to:
Posts (Atom)