Parameters in anonymous function - haskell

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.

Related

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 :-)

Are these premises about folds and recursion right?

When using foldr, the recursion occours inside the function, so,
when the given function doesn't strictly evaluate both sides, and
can return based on the first one, foldr must be a good solution,
because it will work on infinity lists
findInt :: Int -> [Int] -> Bool
findInt z [] = False
-- The recursion occours inside de given function
findInt z (x:xs)
| z == x = True
| otherwise = findInt z xs
equivalent to:
findInt' :: Int -> [Int] -> Bool
findInt' z = foldr (\x r -> if z == x then True else r) False
-- Where False is the "default value" (when it finds [], ex: findInt z [] = False)
A situation when foldr is not appropriate:
addAll :: Int -> [Int] -> Int
addAll z [] = z
-- The recursion occours outside the given function (+)
addAll z (x:xs) = addAll (z + x) xs
In this case, because + is strict (needs to evaluate both sides to return)
it would be greately useful if we applied it in some way which we could
have a redex (reducible expression), to make it possible to avoid thunks
and (when forced to run with previous evaluation, not lazy) in constant
space and without pushing to much onto the stack
(similar to the advantages of a for loop in imperative algorithms)
addAll' :: Int -> [Int] -> Int
addAll' z [] = z
addAll' z (x:xs) = let z' = z + x
in seq z' $ addAll' z' xs
equivalent to:
addAll'' :: Int -> [Int] -> Int
addAll'' z = foldl' (+) z
In this little case, using foldr (inside recursion) doesn't make sense
because it wouldn't make redexes.
It would be like this:
addAll''' :: Int -> [Int] -> Int
addAll''' z [] = z
addAll''' z (x:xs) = (+) x $ addAll''' z xs
The main objective of this question is first, know whether my premises are
right or where they could be better and second, help to make it more clear
for others who are also learning Haskell the differences between inside and
outside recursion, among the approaches, to have it clear in mind which one
could be more appropriated to a given situation
Helpful links:
Haskell Wiki
Stackoverflow - Implications of foldr vs. foldl (or foldl')
Aside from the fact that foldr is the natural catamorphism of a list, while foldl and foldl' are not, a few guidelines for their use:
you are correct on that foldr will always return, even on infinite lists, as long as the function is non-strict in its second argument, since the elements of the list are made available to the first argument of the function immediately (as opposed to foldl and foldl', where the elements of the list are not available to the first argument of the function until the list has been entirely consumed);
foldl' will be a better choice for non-infinite lists if you want to ensure constant space, since it's tail recursive, but it will always parse the entire list regardless of the strictness in the evaluation of the arguments to the function passed to it;
in general, foldr is equivalent to recursion, while foldl and foldl' are analogous to loops;
because of the fact that foldr is the natural catamorphism, if your function needs to recreate the list (for example, if your function is just the list constructor ':'), foldr would be more adequate;
with respect to foldl vs. foldl', foldl' is usually preferable because it will not build a huge thunk but, if the function passed to it is non strict in its first argument and the list is not infinite, foldl may return while foldl' may give an error (there is a good example in the Haskell wiki).
As a side note, I believe that you are using the term "inside recursion" to define foldr and "outside recursion" for foldl and foldl', but I haven't seen these terms before in the literature. More commonly these functions are just referred to as folding from the right and folding from the left respectively, terms that while may not be exactly correct, they give a good notion of the order in which the elements of the list are passed to the function.

using reverse on a self-defined list in Haskell

I did a self-defined data type called Queue and trying to enqueue Integers at the end of the "list".
data Queue = Ele Int Queue | Nil
-- [..] some other Functions
enqueue :: Int -> Queue -> Queue
enqueue x Nil = (Ele x Nil)
enqueue x (Ele _ restEles) = reverse (Ele x reverse restEles)
I get the error:
"Couldn't match expected type Queue' with actual type[a0]'".
I think that is, because the function doesn't know how to handle my datatype. Am I right here? How can I fix this? Do I have to write my own reverse function? And if could you help me with that, because I am still learning Haskell and don't understand this:
reverse = foldl (flip (:)) []
Yes, you have defined a new datatype. Even though it's structurally similar to lists, Haskell will treat it as completely different. So you have to define a new reverse function indeed, or alternatively, define a function converting your type into a standard list and back.
But for enqueue you do not necessarily need reverse. You can just recursively invoke enqueue on restEles in the case for Ele and put the first element back in front of the result.
Here's a pattern for the directly recursive definition for you to complete:
enqueue :: Int -> Queue -> Queue
enqueue x Nil = Ele x Nil
enqueue x (Ele firstEle restEles) = ...
For ..., you have to do what I said above: call enqueue recursively on the rest of the
elements and put the first elements back on top.
The type of reverse is:
reverse :: [a] -> [a]
Queue is not a [a]. You need to implement your own reverseQueue function that understands your data type.
As for the second part of your question:
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []
First, make sure you understand foldl. It's a powerful high-order function, which means it can be used to implement a lot of other functions (sum,map,filter and of course reverse). You can read about it here.
Now, let's take a look at a simpler version:
reverse :: [a] -> [a]
reverse xs = foldl (\ys y -> y:ys) [] xs
\ys y -> y:ys is a very simple function: it takes a list (ys) and a value (y) and insert the value before the list (y:ys). So our course of plan is: start with the empty list ([]), insert the first item in xs to its left, take the result and insert the second item to its left and so on.
Let's simulate it with a simple list - [1,2,3]:
We start with the empty list - []
Add the first item (1) to it's left: [1]
Add the second item (2) to the left of [1]: [2,1]
Add the third item (3) to the left of [2,1]: [3,2,1]
And we've successfully reversed [1,2,3].
Now, flip is a function that takes a function and "flips" it's arguments. so if subtract a b is a-b, then (flip subtract) a b is equal to subtract b a - b-a. So if (:) is a function that takes an item y and a list ys and adds the item to the beginning of the list, then flip (:) is the same function with flipped arguments - it takes a list and an item, much like our function - \ys y -> y:ys. So we can replace the two of them:
reverse :: [a] -> [a]
reverse xs = foldl (flip (:)) [] xs
And now we write in pointfree style and eliminate xs from both sides of the equation and get the final version:
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []

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.

explain how to use this specific function of foldl

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

Resources