Search code examples
haskelllambdafunctional-programmingfoldcartesian-product

It is hard to understand to a transform foldr in cartesian product


I follow On Barron and Strachey's cartesian product function to understand the combination of high order function.

There is a important transform I got and I think it is not easy to understand it straightforward:

h [] xss = []
h (x : xs) xss =
 foldr f (h xs xss) xss where 
    f xs ys = (x: xs) : ys

to equal this :

h'' xs xss = 
foldr g [] xs where
    g x zss = foldr f zss xss where 
        f xs ys = (x : xs) : ys

Even I got these helper:

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z [] = z
foldr f z (a:as) = f a (foldr f z as) 

-- change the name
h' :: (a -> b -> b) -> b -> [a] -> b
h' f z [] = z
h' f z (a:as) = f a (h' f z as)  

So my question is: Is it easy to explain the transform?


Solution

  • Start by making an inner function without the second argument xss that does the standard list recursion only:

    h []     xss = []
    h (x:xs) xss = foldr f (h xs xss) xss
      where 
        f xs ys = (x:xs) : ys
    
      -->
    
    h xs xss = h' xs
      where
        h' []     = []
        h' (x:xs) = foldr f (h' xs) xss
          where
            f xs ys = (x:xs) : ys
    

    Then let's see how we abstract out the recursion pattern in h' with another helper function that acts on x and the recursive call result h' xs only:

    h xs xss = h' xs
      where
        h' []     = []
        h' (x:xs) = g x (h' xs)
        g x zss = foldr f zss xss
          where 
            f xs ys = (x:xs) : ys
    

    which is just that helper function that we would pass to foldr if we didn't want to explicitly write out the list recursion in h':

    h xs xss = foldr g [] xs
      where
        g x zss = foldr f zss xss
          where 
            f xs ys = (x:xs) : ys