Implementing last with foldr1 - haskell

I've a problem with implementing the last function using foldr1. I assume that it takes the right most element and treats it like the accumulator value, then applies binary function to the accumulator and its neighbor until it reaches the beginning of a given list. However, the code shown below doesn't work. Could someone tell me what's wrong with it? Instead of returning the last element it prints out the first one
last' list = foldr1 (\acc _ -> acc) list

foldr :: (a -> b -> b) -> b -> [a] -> b
As you can see, foldr makes the accumulator the second argument, while the value from the list is the first. foldr1 behaves the same way. So, as Lee said, you need to have your lamdba return the second argument rather than the first. Alternatively, you could say foldr1 (flip const)

Related

How to use groupBy on a list of tuples?

How can I group this list by second element of tuples:
[(3,2),(17,2),(50,3),(64,3)]
to get something like:
[[(3,2),(17,2)],[(50,3),(64,3)]]
I'm actually a newcomer to Haskell...and seems to be falling in love with it. Hope you would help me find an efficient way.
It sounds like you've already identified that you want Data.List.groupBy. The type of this function is
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
So it takes a binary predicate, i.e. an equivalence relation determining how to group elements. You want to group elements by equality on the second term of a pair, so you want
groupBy (\x y -> snd x == snd y) myList
Where snd is a built-in function that gets the second element of a pair.
Incidentally, this pattern of "apply a function to two arguments and then apply a binary function to the results" is very common, especially when calling Data.List functions, so Data.Function provides on.
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
Weird signature, but the use case is just what we want.
((+) `on` f) x y = f x + f y
So your desired groupBy can be written as
groupBy ((==) `on` snd)
Note that groupBy only finds consecutive equal elements. You didn't indicate whether you wanted consecutive equal elements or all equal elements, but if you want the latter, then I don't believe Haskell base provides that function, though you could certainly write it recursively yourself.

Haskell - counting with foldr

Working on a Haskell problem, fairly new to the language. I am trying to count the occurence of tuple values that are present in the list of tuples.
My tuples look like this: [(5, [7,2]), (2,[5,7,1,6])]
So far, using foldr, I have done this:
testFunc = foldr (\x-> const succ) 0
However, this only retrieves the count of the left side of the tuple. I am a little confused, how to solve this?
-- Expected output: 6
-- Current output: 2
The type of foldr is:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
This means that the function it's talking should take the current value and the accumulator and will return a value of the same type as the accumulator. It then takes an initial value for the accumulator, and finally the Foldable thing to iterate over.
The accumulator is clearly the count, and for an empty list, it'll be zero, so there's our initial accumulator value.
We then just have to add the length of the list to that accumulator each time through. We can pattern match this data out. We'll use _ for the first item in each tuple, because we just don't care about that value.
Prelude> testData = [(5, [7,2]), (2,[5,7,1,6])]
Prelude> foldr (\(_, lst) count -> count + length lst) 0 testData
6
Prelude>

Confused about parameters in Haskell lambdas

I've been learning Haskell recently and came across something I don't quite understand: the parameters of a lambda function.
In the Learn You a Haskell for Great Good book, chap. 5, there are the following two functions:
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldr (\x acc -> if x == y then True else acc) False ys
reverse' :: [a] -> [a]
reverse' = foldl (\acc x -> x : acc) []
In the first function, the accumulator is listed as the lambda's second parameter, but then is the first to follow the lambda for foldl, which I took to mean it would be the first, not the second, thus, defying expectations.
Whereas, in the second function, it follows expectations, showing up as the lambda's first parameter, making the list that reverse' takes as a parameter the second for the lambda.
I tested both functions and they work as expected. I also noticed that one function involves a right fold and the other a left fold, but I'm not sure why that would alter the meaning of the parameters.
QUESTION: Can someone explain what I'm missing? Why are the parameters seeming to swap places?
foldl and foldr expect the accumulating function to have different formats. The two functions have the following types:
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
You're correct that in foldr, the accumulator is the second argument, and in foldl it's the left.
While this may seem unintuitive, it may help to think of foldl and foldr in terms of how they associate values in a list, the following images come from the "fold" page on the Haskell wiki:
Treating the natural order of the list as left to right: In foldr, the accumulator starts at the right hand side of the list, so it's natural that it's the second argument, while in foldl, the opposite is true.
It is just a convention that the accumulator in foldr is the second argument, and in foldl it is the first argument.
Why was this convention chosen?
The first reason was answered by #Joe. acc is the folded part of the list. In foldl it's left part but in foldr it's right part. So it's natural to provide acc as left operand (the first argument) to folding operator in foldl and as right operand (the second argument) to folding operator in foldr.
foldl should iterate over all the elements in the provided list, while foldr should not. You can provide folding operator to the foldr which can skip rest of elements in the list. The first example does that. The second argument acc in the foldr is thing which is not computed yet, it hold folding the rest of elements. And if you skip it in your folding operator it never be computed. In your example, if x == y you just "return" True (and skip rest elements), else you "return" acc which force to evaluate the next element in the list. So, foldr works lazyly, but foldl works strictly.
In Haskell is another convention. When operator can works lazyly then it usually have the first argument with strict semantic and the second with non strict. For example: &&, || are this sort of operators.
False && undefined => False
True || undefined => True
Folding operator in your the first example is lazy too.
(\x acc -> if x == y then True else acc) y undefined => True
And it can be rewrite in terms of || like this:
(\x acc -> x == y || acc)
Combining above reasons together we have what we have :-)

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.

How can I iterate over a string without recursion?

isTogether' :: String -> Bool
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
For the above code, I want to go through every character in the string. I am not allowed to use recursion.
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
If I've got it right, you are interested in getting consequential char pairs from some string. So, for example, for abcd you need to test (a,b), (b,c), (c,d) with some (Char,Char) -> Bool or Char -> Char -> Bool function.
Zip could be helpful here:
> let x = "abcd"
> let pairs = zip x (tail x)
it :: [(Char, Char)]
And for some f :: Char -> Char -> Bool function we can get uncurry f :: (Char, Char) -> Bool.
And then it's easy to get [Bool] value of results with map (uncurry f) pairs :: [Bool].
In Haskell, a String is just a list of characters ([Char]). Thus, all of the normal higher-order list functions like map work on strings. So you can use whichever higher-order function is most applicable to your problem.
Note that these functions themselves are defined recursively; in fact, there is no way to go through the entire list in Haskell without either recursing explicitly or using a function that directly or indirectly recurses.
To do this without recursion, you will need to use a higher order function or a list comprehension. I don't understand what you're trying to accomplish so I can only give generic advice. You probably will want one of these:
map :: (a -> b) -> [a] -> [b]
Map converts a list of one type into another. Using map lets you perform the same action on every element of the list, given a function that operates on the kinds of things you have in the list.
filter :: (a -> Bool) -> [a] -> [a]
Filter takes a list and a predicate, and gives you a new list with only the elements that satisfy the predicate. Just with these two tools, you can do some pretty interesting things:
import Data.Char
map toUpper (filter isLower "A quick test") -- => "QUICKTEST"
Then you have folds of various sorts. A fold is really a generic higher order function for doing recursion on some type, so using it takes a bit of getting used to, but you can accomplish pretty much any recursive function on a list with a fold instead. The basic type of foldr looks like this:
foldr :: (a -> b -> b) -> b -> [a] -> b
It takes three arguments: an inductive step, a base case and a value you want to fold. Or, in less mathematical terms, you could think of it as taking an initial state, a function to take the next item and the previous state to produce the next state, and the list of values. It then returns the final state it arrived at. You can do some pretty surprising things with fold, but let's say you want to detect if a list has a run of two or more of the same item. This would be hard to express with map and filter (impossible?), but it's easy with recursion:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:y:xs) | x == y = True
hasTwins (x:y:xs) | otherwise = hasTwins (y:xs)
hasTwins _ = False
Well, you can express this with a fold like so:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:xs) = snd $ foldr step (x, False) xs
where
step x (prev, seenTwins) = (x, prev == x || seenTwins)
So my "state" in this fold is the previous value and whether we've already seen a pair of identical values. The function has no explicit recursion, but my step function passes the current x value along to the next invocation through the state as the previous value. But you don't have to be happy with the last state you have; this function takes the second value out of the state and returns that as the overall return value—which is the boolean whether or not we've seen two identical values next to each other.

Resources