How to rewrite a fold with anonymous function in Haskell into a regular function?

Viewed 276

I am trying to teach myself functional programming using Haskell.

I have hard time understanding currying and lambdas.

This is a function that generates a list of prfixes of a list (outputs a list of lists).

foldr (\element accumulator -> [] : map (element:) accumulator) [[]]

I am trying to rewrite it as a regular function without lambda to help me understand how lambdas work. How would I do it? I am stuck. Would I need a helper function? Thank you.

3 Answers

Yes you will need a helper function. where clauses are a great place to put helpers like this. where clauses are attached to a definition, so I will need to name your function (I have named it inits). Start by just moving the expression out verbatim.

inits :: [a] -> [[a]]
inits = foldr helper [[]]
    where
    helper = \element accumulator -> [] : map (element:) accumulator

Then you can move the lambda arguments on the right to parameter bindings on the left, which means the same thing:

inits :: [a] -> [[a]]
inits = foldr helper [[]]
    where
    helper element accumulator = [] : map (element:) accumulator

(You can also just do one parameter:

    helper element = \accumulator -> [] : map (element:) accumulator

These are all equivalent.)

Sounds to me like you're looking for a pointfree form. Yes, it can be done.

inits :: [a] -> [[a]]
inits = foldr ((([]:).) . map . (:)) [[]]

Try it online!

Your lambda has turned into (([]:).) . map . (:). Not very pretty, huh? And much more difficult to understand. I suggest you shy away from this approach.

In general,

foldr g [[]] []            =  [[]]
foldr g [[]] [a,b,c, ...]  =  g a (foldr g [[]] [b,c, ...]) 

Your function g is ( \ x y -> [] : map (x:) y ) i.e.

                    g x y  =  [] : map (x:) y

Thus with your g we have

foldr g [[]] [a,b,c, ...]  =  [] : map (a:) (foldr g [[]] [b,c, ...])

Replacing foldr g [[]] with just foo, and pseudocode [a,b,c, ...] with the valid pattern (a:bc), we get

foo          []            =  [[]]
foo          (a:bc)        =  [] : map (a:) (foo           bc       )

which is "a regular function" without lambda and without a where clause.

Related