2

I am trying to prove the following statement by structural induction:

foldr f st (xs++yx) = f (foldr f st xs) (foldr f st ys)        (foldr.3)

However I am not even sure how to define foldr, so I am stuck as no definitions have been provided to me. I now believe that foldr can be defined as

foldr f st [] = st                                             (foldr.1)
foldr f st x:xs = f x (foldr f st xs)                          (foldr.2)

Now I want to start working on the base case passing the empty list to foldr. I have this, but I don't think it is correct.

foldr f st ([]++[]) = f (foldr f st []) (foldr f st [])
LHS:
    foldr f st ([]++[]) = foldr f st []                        by (++)
    foldr f st [] = st                                         by (foldr.1)
RHS:
    f (foldr f st []) (foldr f st []) = f st st                by (foldr.1)
    = st                                                       by definition of identity, st = 0

LHS = RHS, therefore base case holds

Now this is what I have for my inductive step:

Assume that:
  foldr f st (xs ++ ys) = f (foldr f st xs) (foldr f st ys)        (ind. hyp)

Show that:
  foldr f st (x:xs ++ ys) = f (foldr f st x:xs) (foldr f st ys)    (inductive step)

LHS:
    foldr f st (x:xs ++ ys) = f x (foldr f st xs) (foldr f st ys)  (by foldr.2)
RHS:
    f (foldr f st x:xs) (foldr f st ys) = 
  = f f x (foldr f st xs) (foldr f st ys)                          (by foldr.2)
  = f x (foldr f st xs) (foldr f st ys)

LHS = RHS, therefore inductive step holds. End of proof.

I am not sure if this proof is valid. I need some help in determining if it correct and if not - what part of it is not.

Rumen Hristov
  • 867
  • 2
  • 13
  • 29
  • 2
    Uh...no. It's true that `foldr f st (xs ++ ys) = foldr f (foldr f st ys) xs`, though. – Louis Wasserman Nov 17 '14 at 04:50
  • this only holds if `f` is associative, ``(a `f` b) `f` c == a `f` (b `f` c)`` _(but `foldr` in general allows for asymmetric type of `f :: a -> b -> b`)_, and `st` is its right zero: `f a st == a` _(counterexample: `foldr (+) 1 (a++b) = foldr (+) 1 a + foldr (+) 1 b` **`- 1`**)_. – Will Ness Nov 17 '14 at 14:33

1 Answers1

2

First: you can find the definition for many basic Haskell functions via the API documentation, which is available on Hackage. The documentation for base is here. foldr is exported in Prelude, which has a link to its source code:

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
          where
            go []     = z
            go (y:ys) = y `k` go ys

It's defined like this for efficiency reasons; look up "worker-wrapper." It's equivalent to

foldr f st [] = st
foldr f st (y:ys) = f y (foldr f st ys) 

Second: In your desired proof, the type of f must be a -> a -> a, which is less general than a -> b -> b.

Let's work through the base case (xs = ys = []).

foldr f st ([]++[]) = f (foldr f st []) (foldr f st [])
-- Definition of ++
foldr f st []       = f (foldr f st []) (foldr f st [])
-- Equation 1 of foldr
st                  = f st              st

This equation does not hold in general. To proceed with the proof, you'll have to assume that st is an identity for f.

You'll also have to assume, in the non-base case, that f is associative, I believe. These two assumptions, combined, indicate that f and st form a monoid. Are you trying to prove something about foldMap?

Christian Conkle
  • 5,932
  • 1
  • 28
  • 52
  • So how should the base case look then? LHS: foldr f st [] = st by definition above for []. RHS = st. So base case hold. I don't think this works. – Rumen Hristov Nov 17 '14 at 04:15
  • I think you're mixing up LHS and RHS? You say that `RHS = st`, but your "proof" in the edited question is for the LHS, not the RHS. Also, please be careful not to fundamentally change the question with your edits. You can add addenda, or even post your own answer if appropriate. – Christian Conkle Nov 17 '14 at 05:04
  • My bad about the RHS. I changed that. – Rumen Hristov Nov 17 '14 at 05:19
  • But is this really the base case? Isn't the base case: foldr f st ([] ++ ys) = f (foldr f st []) (foldr f st ys), where only xs is the empty list? – Rumen Hristov Nov 17 '14 at 05:22
  • Sure; that leads to `foldr f st ys = f st (foldr f st ys)` which works if `f st y = y` (flipped left-to-right). If you do it the other way round you get `f x st = x`. Compare that to the [monoid laws](http://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html). – Christian Conkle Nov 17 '14 at 06:20
  • I will soon update my question with a new part to reflect my inductive step. I think I figured out the base case. Would you be able to review my inductive step when I post it? – Rumen Hristov Nov 17 '14 at 06:35