explain how to use this specific function of foldl - haskell

sum :: (Num a) => [a] -> a
sum xs = foldl (\acc x -> acc + x) 0 xs
foldl is folds the list up from the left side. So first we get the acc=0 and put the list xs to x ,then doing the function ->acc+x.After calculation, we get the new acc which is equal to acc+x. But why is that? I think this result of acc+x is the new value of x based on the function x->acc+x.

Let's take a look at your definition of sum
sum :: (Num a) => [a] -> a
sum xs = foldl (\acc x -> acc + x) 0 xs
Let's also take a peek at foldl's signature:
foldl :: (a -> b -> a) -> a -> [b] -> a
Hmm, ok, what do we have to feed foldl in order to get the value at the very, very end (->a)?
It needs a curried function (a->b->a). All though not accurate, for brevity's sake, we'll say its a function that takes two arguments (but you and I know that really, it takes one argument and returns another function that takes one argument).
It needs a value of type a. Notice that our curried function from Step 1. takes something of type a and returns something of type a. Interesting...hmmm...
It needs a list of type b. Notice our curried function from Step 1 takes, as well as something of type a, something of type b.
So, do we give it what it wants?
We give it (\acc x -> acc + x). This is an anonymous function, or lambda, that takes two arguments, (remember, it's curried, though), acc and x, and return's their sum.
We give it 0 as our starting value
We give it xs as the list to fold.
Ok dokie. So, let's just let foldl work its Haskell magic. Let's imagine we called sum [1,2,3]
foldl calls our function (\acc x -> acc + x), using 0 for acc and the first value of xs, 1.
0 + 1
This result does not get stored away in acc or x, since they are just arguments in our little lambda function. foldl is going to use that value (see SanSS's answer for the specific implementation).
Remember that the result of our lambda function is the same type as the first parameter? foldl can use that previous sum and pass it back to the lambda function, along with the second element.
(0 + 1) + 2
And again until it has done this for all the elements:
((0 + 1) + 2) + 3
6
As pointed out by Dan, this is the same if you had done:
sum xs = foldl (+) 0 xs
You can tell more easily with this function that we aren't just 'setting' some variable and adding onto it.
Hope this helps.
Side note:
For your definition of sum, you don't have to explicitly state that sum takes xs. You could leave it as:
sum = foldl (\acc x -> acc + x) 0
This takes advantage of currying, because if we provide foldl just its first two arguments -- a curried function like (a->b->a) and a value of type a -- what do we get?
[b] -> a
A function that takes a list of type b and returns a value of type a! This is called pointfree style. Just something to consider :-)

You should look at the definition of foldl:
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
foldl recieves a funcion which takes 2 arguments, a value (the "starter value" or accumulator) and a list.
In case the list is empty it returns the current calculation.
If the case is not empty then it calls recursively with the same function as function, the accumulator is the result of the invocation of the function using the accumulator as the first argument and the first element of the list as the second argument and the tail of the list is used as the list for the recursive call.
So the lambda function used in sum becomes quite clear it takes acc as first argument and the element of the list as second argument and return the sum of both.
The result of the invocations for:
sum [1,2,3] = ((0 + 1) + 2) + 3 = 6

From your question, it sounds like you don't understand how the lambda function (\acc x -> acc + x) works here.
The function is not x->acc+x, but acc x->acc + x. In fact, you could rewrite the "sum" equation as
sum xs = foldl (+) 0 xs
Since (\acc x -> acc + x) is the same as (+)
I suggest you (re)read http://learnyouahaskell.com/higher-order-functions#lambdas

Related

Haskell Functions (map,foldr, foldl)

I am struggling to think of a way to utilize these functions for this beginner level coding class that I am taking to learn functional programming in Haskell. The functions I have to write are shown below, asum is supposed to turn a list of integers [a1,a2,..,an] into the alternating sum a1-a2+a3-a4+.… and I am not sure how to approach it with these functions. The xor function is supposed to that computes the XOR of a list of Booleans. I need some help to understand how to use these functions and it would greatly appreciated. I am also new to Haskell so any explanations would help. Thanks I have to use map foldr foldl.
asum :: (Num a) => [a] -> a
xor :: [Bool] -> Bool
I would say start by running the following, one by one, in GHCi:
:t foldr
:info foldr
:doc foldr
:t foldl
:info foldl
:doc foldl
:t map
:info map
:doc map
Or better, open hoogle.haskell.org and search each of the above mentioned functions and click on the first link.
But I agree that Haskell documentation are difficult to read, especially for beginners. I'm a beginner and I have a lot of difficulty reading and understanding them.
Here's a function that uses map and foldr to show how foldr works:
printFoldr xs = foldr (\x acc -> "(" ++ x ++ " + " ++ acc ++ " )") "0" $ map show xs
Now running watch this:
printFoldr [1..5]
-- outputs the following:
"(1 + (2 + (3 + (4 + (5 + 0 ) ) ) ) )"
This shows us how foldr is evaluated. Before going into how foldr is evaluated, let's look briefly at map.
map show [1..5]
-- outputs the following:
["1","2","3","4","5"]
This means that map takes 2 arguments. A list and a function that is applied to each element of the list. The result is a new list with the function applied to each element. Thus, applying show to each number outputs their string representation.
Back to foldr. foldr takes 3 arguments:
a function of type a -> b -> b
an initial value of type b
a list of type [a]
foldr takes each and every value of the provided list and applies this function to it. What is special is that map retains the output of the function over each iteration and passes it to the function as its second argument on the next run. Therefore it is convenient to write the function that is passed foldr as follows: (\el acc -> do something). Now on the next iteration of foldr, acc will hold the value of the previous run and el will be the current element from the list. BTW, acc stands for accumulator and el for element. This enables us to reduce elements of the provided list to something completely new.
As you can see in printFoldr, the initial value is just an empty string but it gradually adds the lists elements to it showing how it would have reduced the elements of the list to their sum.
Here's an idea:
a1-a2+a3-a4+...
=
a1-(a2-(a3-(a4-(...(an-0)...))))
This fits pretty well to the foldr pattern of recursion,
foldr f z [a1,a2,a3,a4,...,an]
=
a1`f`(a2`f`(a3`f`(a4`f`(...(an`f`z)...))))
So it can be coded by setting f = ... and z = ... and calling
asum :: (Num a) => [a] -> a
asum xs = foldr f z xs
where
f = (...)
z = (...)
You will need to complete this definition.
For the XOR of a list of Booleans, assuming it is to be True if one and only one of them is True, and False otherwise, we can imagine this sequence of transformations:
[ True, False, False, True, True, False, ...]
==>
[ t, f, f, t, t, f, ...]
where t and f are some specially chosen numbers. And then we can find the sum of this second list (not alternating sum, just a sum of a list of numbers) and check whether it is equal to ... some (other?) special number, let's call it n1:
xor :: [Bool] -> Bool
xor bools = (aNumber ... n1)
where
list1 = bools
list2 = fun1 transform list1
transform False = f
transform True = t
f = ...
t = ...
aNumber = sum list2
n1 = ...
fun1 = ...
sum listOfNums = ...
fun1 is the function which transforms each element of its argument list according to the given function, called transform above. It is one of the two functions left from the three you were given, considering we've already been using foldr.
sum is to be implemented by using the last function that's left.
FYI,
map foo [a1,a2,a3,...,an]
=
[foo a1, foo a2, foo a3, ..., foo an]
and
foldl f z [a1,a2,a3,...,an]
=
((((z`f`a1)`f`a2)`f`a3)...)`f`an

Partial functions application and folds in haskell

I'm trying to learn Haskell by solving exercises and looking at others solutions when i'm stuck. Been having trouble understanding as functions get more complex.
-- Ex 5: given a list of lists, return the longest list. If there
-- are multiple lists of the same length, return the list that has
-- the smallest _first element_.
--
-- (If multiple lists have the same length and same first element,
-- you can return any one of them.)
--
-- Give the longest function a suitable type.
--
-- Examples:
-- longest [[1,2,3],[4,5],[6]] ==> [1,2,3]
-- longest ["bcd","def","ab"] ==> "bcd"
longest :: (Foldable t, Ord a) => t [a] -> [a]
longest xs = foldl1 comp xs
where
comp acc x | length acc > length x = acc
| length acc == length x = if head acc < head x then acc else x
| otherwise = x
So foldl1 works as follows - input: foldl1 (+) [1,2,3,4] output: 10. As I understand it, it takes a function applies it to a list and "folds" it. The thing I don't understand is that comp acc x compares two lists and outputs the larger length list.
The thing I don't understand is with longest xs = foldl1 comp xs. How are two lists provided to comp to compare and what is foldl1 "folding" and what is the start accumulator?
Here is another shorter example of another fold that I thought I understood.
foldl - input: foldl (\x y -> x + y) 0 [1,2,3] output: 6
It starts at 0 and adds each element from left one by one. How does foldl exactly apply the two variables in the anonymous function. For instance if the anonymous function was (\x y z-> x + y + z) it would fail which I don't yet understand why.
I think your current notion of what foldl1/foldl does is not quite accurate. As others already explained foldl1 f (x:xs) == foldl f x xs so the first value in the list is taken as an accumulator.
You say that foldl1 (+) list takes each value of the list "one by one" and computes the sum. I think this notion is misleaing: Actually you do always take two values, add them and get an intermediate result. And you repeat that over and over again with one of the values being the intermediate result of the last. I really like following illustration:
Source
If you start to think about these intermediate values, it will make more sense that you always get the largets one.
I think it is easiest to understand if you look at a symbolic example:
foldl k z [a, b, c] = k (k (k z a) b) c
foldl1 k [a, b, c] = k (k a b) c
As you can see foldl1 just starts with the first two arguments and then adds on the rest one by one using k to combine it with the accumulator.
And foldl starts by applying k to the initial accumulator z and the first element a and then adds on the rest one by one.
The k function only ever gets two arguments, so you cannot use a function with three arguments for that.

Parameters in anonymous function

I've been practicing with anonymous functions and got the following:
takeWhile' :: (a -> Bool) -> [a] -> [a]
takeWhile' f xs = foldl (\x y z -> if (f x) && z then x : y else y) xs [] True
which is basically a rewrite of the takeWhile function already in Haskell.
For those who don't know, the takeWhile function takes a list and a function and returns a new list with every element in the original list that satisfies the function until one of them gives false.
From my point of view everything seems to be correct, I have 3 arguments x y and z ready to use in my anonymous function, x being the list of numbers, y the empty list where I'll be inserting every element and z is basically a debouncer so that if one of the elements doesn't meet the requirements, we don't insert any more.
And yet Haskell gives me the following error:
"Occurs check: cannot construct the infinite type: a ~ Bool -> [a]"
Any idea why?
The fold function in fold takes as parameters the accumulator x, and the element y. So there is no z that is passed.
But even if that was somehow possible, there are still other issues. x is the accumulator here, so a list, that means that x : y makes no sense, since (:) :: a -> [a] -> [a] takes an element and a list, and constructs a new list.
You can however easily make use of foldr to implement a takeWhile function. Indeed:
takeWhile' p = foldr (\x -> if p x then (x :) else const []) []
We here thus check if the predicate holds, if that is the case, we preprend the accumulator with x. If not, we return [], regardless of the value of the accumulator.
Due to the laziness of foldr, it will not look for elements after an element has failed the accumulator, since const [] will ingore the value of the accumulator.

Haskell naive duplicate filtering

I do not understand a sample solution for the following problem: given a list of elements, remove the duplicates. Then count the unique digits of a number. No explicit recursion may be used for either problem.
My code:
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = foldr (\x ys -> x:(filter (x /=) ys)) []
differentDigits :: Int -> Int
differentDigits xs = length (removeDuplicates (show xs))
The solution I am trying to understand has a different definition for differentDigits, namely
differentDigits xs = foldr (\ _ x -> x + 1) 0 ( removeDuplicates ( filter (/= '_') ( show xs )))
Both approaches work, but I cannot grasp the sample solution. To break my question down into subquestions,
How does the first argument to filter work? I mean
(/= '_')
How does the lambda for foldr work? In
foldr (\ _ x -> x + 1)
^
the variable x should still be the Char list? How does Haskell figure out that actually 0 should be incremented?
filter (/= '_') is, I'm pretty sure, redundant. It filters out underscore characters, which shouldn't be present in the result of show xs, assuming xs is a number of some sort.
foldr (\ _ x -> x + 1) 0 is equivalent to length. The way foldr works, it takes the second argument (which in your example is zero) as the starting point, then applies the first argument (in your example, lambda) to it over and over for every element of the input list. The element of the input list is passed into the lambda as first argument (denoted _ in your example), and the running sum is passed as second argument (denoted x). Since the lambda just returns a "plus one" number on every pass, the result will be a number representing how many times the lambda was called - which is the length of the list.
First, note that (2) is written in so called point free style, leaving out the third argument of foldr.
https://en.wikipedia.org/wiki/Tacit_programming#Functional_programming
Also, the underscore in \_ x -> x + 1 is a wild card, that simply marks the place of a parameter but that does not give it a name (a wild card works as a nameless parameter).
Second, (2) is a really nothing else than a simple recursive function that folds to the right. foldr is a compact way to write such recursive functions (in your case length):
foldr :: (a -> b -> b) -> b -> [a]
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
If we write
foldr f c ls
ls is the list over which our recursive function should recur (a is the type of the elements).
c is the result in the base case (when the recursive recursive function is applied on an empty list).
f computes the result in the general case (when the recursive function is applied on a non-empty list). f takes two arguments:
The head of the list and
the result of the recursive call on the tail of the list.
So, given f and c, foldr will go through the list ls recursively.
A first example
The Wikipedia page about point free style gives the example of how we can compute the sum of all elements in a list using foldr:
Instead of writing
sum [] = 0
sum (x:xs) = x + sum xs
we can write
sum = foldr (+) 0
The operator section (+) is a 2-argument function that adds its arguments. The expression
sum [1,2,3,4]
is computed as
1 + (2 + (3 + (4)))
(hence "folding to the right").
Example: Multiplying all elements.
Instead of
prod [] = 1
prod (x:xs) = x * prod xs
we can write
prod = foldr (*) 1
Example: Remove all occurrences of a value from a list.
Instead of
remove _ [] = []
remove v (x:xs) = if x==v then remove v xs else x:remove v xs
we can write
remove v = foldr (\x r -> if x==v then r else x:r) []
Your case, (2)
We can now fully understand that
length = foldr (\ _ x -> x + 1) 0
in fact is the same as
length [] = 0
length (x:xs) = length xs + 1
that is, the length function.
Hope this recursive view on foldr helped you understand the code.

Define function in Haskell using foldr

I'm trying to define a function in Haskell using the foldr function:
fromDigits :: [Int] -> Int
This function takes a list of Ints (each on ranging from 0 to 9) and converts to a single Int. For example:
fromDigits [0,1] = 10
fromDigits [4,3,2,1] = 1234
fromDigits [2,3,9] = 932
fromDigits [2,3,9,0,1] = 10932
Anyway, I have no trouble defining this using explicit recursion or even using zipWith:
fromDigits n = sum (zipWith (*) n (map ((^)10) [0..]))
But now I have to define it using a foldr, but I don't know how to get the powers of 10. What I have is:
fromDigits xs = foldr (\x acc -> (x*10^(???)) + acc) 0 xs
How can I get them to decrease? I know I can start with (length xs - 1) but what then?
Best Regards
You were almost there:
your
fromDigits xs = foldr (\x acc -> (x*10^(???)) + acc) 0 xs
is the solution with 2 little changes:
fromDigits = foldr (\x acc -> acc*10 + x) 0
(BTW I left out the xs on each sides, that's not necessary.
Another option would be
fromDigits = foldl (\x acc -> read $ (show x) ++ (show acc)) 0
The nice thing about foldr is that it's so extemely easy to visualise!
foldr f init [a,b, ... z]
≡ foldr f init $ a : b : ... z : []
≡ a`f b`f`... z`f`init
≡ f a (f b ( ... (f z init)...)))
so as you see, the j-th list element is used in j consecutive calls of f. The head element is merely passed once to the left of the function. For you application, the head element is the last digit. How should that influence the outcome? Well, it's just added to the result, isn't it?
15 = 10 + 5
623987236705839 = 623987236705830 + 9
– obvious. Then the question is, how do you take care for the other digits? Well, to employ the above trick you first need to make sure there's a 0 in the last place of the carried subresult. A 0 that does not come from the supplied digits! How do you add such a zero?
That should really be enough hint given now.
The trick is, you don't need to compute the power of 10 each time from scratch, you just need to compute it based on the previous power of ten (i.e. multiply by 10). Well, assuming you can reverse the input list.
(But the lists you give above are already in reverse order, so arguably you should be able to re-reverse them and just say that your function takes a list of digits in the correct order. If not, then just divide by 10 instead of multiplying by 10.)

Resources