I came across this code and it works but I don't know why. I will attempt to convey the parts that I understand but I don't get the full picture. Here is the code:
church :: Int -> (c -> c) -> c -> c
church 0 _ arg = arg
church n f arg = foldr (\x acc -> f acc) arg [1..n]
When running this input on the Prelude,
church 4 tail "ABCDEFGH"
this is the answer:
"EFGH"
I know how foldr works, I can walk through an example of foldr:
foldr (/) 2 [8,12,24,4]
What happens here is:
4/2 = 2, 24/2 = 12, 12/12 = 1, 8/1 = 8
I get the desired output 8, as described in the second example of this page:
As for this question, I know why "EFGH" is the answer. The tail is applied four times and it goes like this:
tail "ABCDEFGH" = "BCDEFGH",
tail "BCDEFGH" = "CDEFGH"
tail "CDEFGH" = "DEFGH"
tail "DEFGH" = "EFGH"
But, in this code, this is the procedure when I write it out:
foldr (\x acc -> tail acc) "ABCDEFGH" [1, 2, 3, 4]
From what I have described for foldr above, foldr applies tail and "ABCDEFGH" to 4, since 4 is the last element. But, I can't wrap my head around how "ABCDEFGH" is applied with a tail to 4. From my example, it was easy because (/) divides 2 elements, one from the list and the other being the second argument. However, in this code's case, tail is used between an element from a list and another list. I do not understand that. Can anybody help me out by going through element by element, like how I described in my example?
Note that x isn't used anywhere to the right of the ->. Thus, the numbers in the list aren't being used. It could be a list of units and still work the same: foldr (\x acc -> tail acc) "ABCDEFGH" [(), (), (), ()] The only purpose of the list is to encode the number of times to do tail in its length. It may also help your understanding if you replace \x acc -> tail acc with the equivalent expression const tail.
Related
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.
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.
I've looked at different folds and folding in general as well as a few others and they explain it fairly well.
I'm still having trouble on how it would work in this case.
length :: [t] -> Int
length list = foldr (+) 0 (map (\x ->1) list)
Could someone go through that step by step and try to explain that to me.
And also how would foldl work as well.
(map (\x ->1) list) takes the list and turns it into a list of 1 values:
(map (\x ->1) ["a", "b", "c"]) == [1, 1, 1]
Now, if you substitute that in the original foldr, it looks like this:
foldr (+) 0 [1, 1, 1]
The starting point is 0 and the aggregation function is (+). As it steps through each element in the list, you are basically adding up all the 1 values, and that's how you end up returning the length.
foldr starts from the right and works back to the head of the list. foldl starts from the left and works through the list. Because the aggregation function is (+) :: Num a => a -> a -> a, the ordering of the left and right arguments in (+) is logically inconsequential (with the caveat that foldl has stack overflow problems with large lists because of lazy evaluation)
I am new to Haskell, actually I just started, and I would like to get a small hint to the question I am about to ask.
I am currently trying to get the GCD of a given list. For example, having the list [3, 6, 9] it will return 3.
For the moment, I tought of the following aproach, am I going in a good direction?
let getGCD l = map (\x y -> gcd x y) l
Not quite, you don't want map but rather a fold. map will let you transform every element in the list uniformly, so you give it a local transformation a -> b and it gives you a global transformation ([a] -> [b]). This isn't really what you want.
As a quick primer on folds, there's a whole family of them which all let us express computations which we build up by repeatedly applying a function to an initial value, the next element and the list, and then repeating with the result of that application as the new initial value. So foldl' (+) 0 [1, 2, 3, 4] would so something like
foldl' (+) 0 [1, 2, 3, 4] ==>
foldl' (+) 1 [2, 3, 4] ==>
foldl' (+) 3 [3, 4] ==>
foldl' (+) 6 [4] ==>
foldl' (+) 10 [] ==> -- For empty lists we just return the seed given
10
Can you see how to slot your problem into this framework?
More hints
You want to take a list and compute a result which depends on every element of the list, something like
gcdAll :: [Int] -> Int
gcdAll l = foldl' step initial l
is closer to what you want where step takes the current gcd of the list you've processed so far and the next element of the list and returns the next value and initial is the value to start with (and what is returned if l is empty. Since there isn't really a sane value, I'd instead split this into
gcdAll :: [Int] -> Maybe Int
gcdAll [] = Nothing
gcdAll (h : rest) = Just $ foldl' step h rest
so that you correctly signal the possibility of failure, after all, what's the gcd of nothing?
Note that foldl' is imported from Data.List.
You can recursively use gcd on a list (essentially a fold implementation)
gcd' :: (Integral a) => [a] -> a
gcd' [] = 1
gcd' [x] = x
gcd' (x:xs) = gcd x (gcd' xs)
A GCD is a property of a pair of numbers. So, really, you want to look at pairs of numbers drawn from your list. Ultimately you want to end up with a single GCD for the entire list, but as a first step, you want pairs.
There's a widely-known trick for working with consecutive pairs:
f1 list = zipWith f2 list (tail list)
The zipWith function is a bit like map, but works with a pair of lists. In this case, the original list, and the tail of the original list. (Note that this fails if the list is empty.) If you replace f2 with your gcd function, you now have a new list which is the GCD of each consecutive pair of numbers. And this list is one element shorter than the original:
f1 [x, y, z, w] ==> [gcd x y, gcd y z, gcd z w]
So each time you apply f1 to a list, you get a new, shorter list of GCDs. Apply it enough times, and you should end up with just one element...
I just tackled this one and this would be the quickest, simplest
myGCDMultiple = foldr1 gcd
> myGCDMultiple [3,6,9]
3
I am new to Haskell and I have the following problem. I have to create a list of numbers [f1, f2, f3...] where fi x = x ^ i. Then I have to create a function that applies the fi to a list of numbers. For example if I have a list lis = [4,5,6,7..] the output would be [4^1, 5^2,6^3, 7^4...]. This is what I have written so far :
powers x= [x^y |y<-[1,2,3,4]]
list = [1,2,3,4]
match :: (x -> xs) -> [x] -> [xs]
match f [] = []
match f (x:xs) = (f x) : ( match f xs )
So if I put the list = [1,2,3] the output is [1,1,1,1][2,4,8,16],[3,9,27,81] instead of [1,4,27]
Can you please tell me what is wrong and point me to the right direction?
The first issue is that powers is of type Int -> [Int]. What you really want, I think, is something of type [Int -> Int] -- a list of Int -> Int functions instead of a function that takes an Int and returns a list of Int. If you define powers like so:
powers = [(^y) | y <- [1..4]]
you can use zipWith to apply each power to its corresponding element in the list, like so:
zipWith ($) powers [1,2,3] -- returns [1,4,27]
The ($) applies its left (first) argument to its right (second) argument.
Note that using powers as defined here will limit the length of the returned list to 4. If you want to be able to use arbitrary length lists, you want to make powers an infinite list, like so:
powers = [(^y) | y <- [1..]]
Of course, as dave4420 points out, a simpler technique is to simply use
zipWith (^) [1,2,3] [1..] -- returns [1,4,27]
Your match is the standard function map by another name. You need to use zipWith instead (which you can think of as mapping over two lists side-by-side).
Is this homework?
You are currently creating a list for every input value.
What you need to do is recursively compute the appropriate
power for each input value, like this:
match f [] = []
match f (x:xs) y = (f x y) : (match f xs y+1)
Then, you can call this as match pow [1, 2, 3] 1.
This is equivalent to using zipWith and providing the desired function (pow), your input list ([1, 2, 3]) and the exponent list (a lazy one to infinity list) as arguments.