Haskell Basics of Recursion - haskell

I'm not exactly sure if I'm even supposed to ask more general, nonspecific questions on this platform, but I'm new to writing Haskell and writing code in general and an in-depth explanation would really be appreciated. I'm very used to the typical method of using loop systems in other languages, but as Haskell's variables are immutable, I've found recursion really difficult to wrap my head around. A few examples from the Haskell Wikibook include:
length xs = go 0 xs
where
go acc [] = acc
go acc (_:xs) = go (acc + 1) xs
zip [] _ = []
zip _ [] = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys
[] !! _ = error "Index too large" -- An empty list has no elements.
(x:_) !! 0 = x
(x:xs) !! n = xs !! (n-1)
The first one is kind of self-explanatory, just writing a length function for strings from scratch. The second is like an index search that returns a char at a specified point, and the third I guess kind of transposes lists together.
Despite somewhat knowing what these pieces of code do, I'm having a lot of trouble wrapping my head around how they function. Any and all step-by-step analysis of how these things actually process would be GREATLY appreciated.
EDIT: Thank you all for the answers! I have yet to go through all of them thoroughly but after reading some this is exactly the kind of information I'm looking for. I don't have a lot of time to practice right now, finals soon and all, but during my break and decided to take another crack at recursion with this:
ood x
|rem x 2 == 1 = ood (x-1)
|x <= 0 = _
|otherwise = ood (x-2)
I wanted to attempt to make a small function that prints every odd number starting from x down to 1. Obviously it does not work; it simply only prints 1. I believe it does hit every odd number on the way down, it just does not display it's answers intermittently. If any one of you could take my own attempt at code and show me how to create a successful recursion function it would really help me a lot!

Let's look at how one might construct two of these.
zip
We'll start with zip. The purpose of zip is to "zip" two lists into one. The name comes from the analogy of zipping two sides of a zipper together. Here's an example of how it functions:
zip [1,2,3] ["a", "b", "c"]
= [(1,"a"), (2,"b"), (3,"c")]
The type signature of zip (which is typically the first thing you'd write) is
zip :: [a] -> [b] -> [(a, b)]
That is, it takes a list of elements of type a and a list of elements of type b and produces a list of pairs with one component of each type.
To construct this function, let's go for standard Haskell pattern matching. We have four cases:
The first list is [] and the second list is [].
The first list is [] and the second list is a cons (constructed using :).
The first list is a cons and the second list is [].
The first list is a cons and the second list is also a cons.
Let's work out each of these.
zip [] [] = ?
If you zip together two empty lists, you have no elements to work with, so surely you get the empty list.
zip [] [] = []
In the next case, we have
zip [] (y : ys) = ?
We have an element, y, of type b, but no element of type a to pair it with. So we can only construct the empty list.
zip [] (y : ys) = []
The same happens in the other asymmetrical case:
zip (x : xs) [] = []
Now we get to the interesting case of two conses:
zip (x : xs) (y : ys) = ?
We have elements of the right types, so we can make a pair, (x, y), of type (a, b). That's the head of the result. What's the tail of the result? Well, that's the result of zipping the two tails together.
zip (x : xs) (y : ys) = (x, y) : zip xs ys
Putting all these together, we get
zip [] [] = []
zip [] (y : ys) = []
zip (x : xs) [] = []
zip (x : xs) (y : ys) = (x, y) : zip xs ys
But the implementation you gave only has three cases! How's that? Look at what the first two cases have in common: the first list is empty. You can see that whenever the first list is empty, the result is empty. So you can combine these cases:
zip [] _ = []
zip (x : xs) [] = []
zip (x : xs) (y : ys) = (x, y) : zip xs ys
Now look at what's now the second case. We already know that the first list is a cons (because otherwise we'd have taken the first case), and we don't need to know anything more about its composition, so we can replace it with a wildcard:
zip [] _ = []
zip _ [] = []
zip (x : xs) (y : ys) = (x, y) : zip xs ys
That's produces the zip implementation you copied. Now it turns out that there's a different way to combine the patterns that I think explains itself a bit more clearly. Reorder the four patterns like this:
zip (x : xs) (y : ys) = (x, y) : zip xs ys
zip [] [] = []
zip [] (y : ys) = []
zip (x : xs) [] = []
Now you can see that the first pattern produces a cons and all the rest produce empty lists. So you can collapse all three of the rest, producing the nicely compact
zip (x : xs) (y : ys) = (x, y) : zip xs ys
zip _ _ = []
This explains what happens when both lists are conses, and what happens when that's not the case.
length
The naive way to implement length is very direct:
length :: [a] -> Int
length [] = 0
length (_ : xs) = 1 + length xs
This will give you correct answers, but it's inefficient. When evaluating the recursive call, the implementation needs to keep track of the fact that once it's done, it needs to add 1 to the result. In practice, it likely pushes the 1+ onto some sort of stack, makes the recursive call, pops the stack, and performs the addition. If the list has length n, the stack will reach size n. That's not great for efficiency. The solution, which the code you copied obscures somewhat, is to write a more general function instead.
-- | A number plus the length of a list
--
-- > lengthPlus n xs = n + length xs
lengthPlus :: Int -> [a] -> Int
-- n plus the length of an empty list
-- is n.
lengthPlus n [] = n
lengthPlus n (_ : xs) = ?
Well,
lengthPlus n (x : xs)
= -- the defining property of `lengthPlus`
n + length (x : xs)
= -- the naive definition of length
n + (1 + length xs)
= -- the associative law of addition
(n + 1) + length xs
= -- the defining property of lengthPlus, applied recursively
lengthPlus (n + 1) xs
So we get
lengthPlus n [] = n
lengthPlus n (_ : xs) = lengthPlus (n + 1) xs
Now the implementation can increment the counter argument on each recursive call instead of delaying them till afterwards. Well ... pretty much.
Thanks to Haskell's call-by-need semantics, this isn't guaranteed to run in constant memory. Suppose we call
lengthPlus 0 ["a","b"]
This reduces to the second case:
lengthPlus (0 + 1) ["b"]
But we haven't actually demanded the value of the sum. So the implementation could defer that addition work, creating a chain of deferrals that's just as bad as the stack seen earlier! In practice, the compiler is clever enough that it will work out how to do this right when optimizations are enabled. But if you don't want to rely on that, you can give it a hint:
lengthPlus n [] = n
lengthPlus n (_ : xs) = n `seq` lengthPlus (n + 1) xs
This tells the compiler that the integer argument actually has to be evaluated. As long as the compiler isn't being intentionally obtuse, it will be sure to evaluate it first, clearing up any deferred additions.

I'm not sure exactly which part you're confused by. Perhaps you're just overthinking this? Let's walk through zip slowly.
For arguments' sake, let's say we want to execute zip [1, 2, 3] ['A', 'B', 'C']. What do we do?
We have zip [1, 2, 3] ['A', 'B', 'C']. What now?
The first line ("equation") of the definition of zip says
zip [] _ = []
Is our first argument an empty list? No, it's [1, 2, 3]. OK, so skip this equation.
The second equation of zip says
zip _ [] = []
Is our second argument an empty list? No, it's ['A', 'B', 'C']. So ignore this equation too.
The last equation says
zip (x:xs) (y:ys) = (x, y) : zip xs ys
Is our first argument a non-empty list? Yes! It's [1, 2, 3]. So the first element becomes x, and the rest become xs: x = 1, xs = [2, 3].
Is our second argument a non-empty list? Again, yes: y = 'A', ys = ['B', 'C'].
OK, what do we do now? Well, what the right-hand size says. If I put in some extra brackets, the right-hand side basically says
(x, y) : (zip xs ys)
So we're constructing a new list, which starts with (x, y) (a 2-tuple) and continues with whatever zip xs ys is. So our output is (1, 'A') : ???.
What is the ??? part? Well, it's like we executed zip [2, 3] ['B', 'C']. Go back to the top, walk through again the same way as before. You'll find that this outputs (2, 'B') : ???.
Now we started with (1, 'A') : ???. If we replace that with the thing we just got, we now have (1, 'A') : (2, 'B') : ???.
Take this one step further and we have (1, 'A') : (2, 'B') : (3, 'C') : ???. Here the ??? part is now zip [] []. It should be clear that the first equation says this is [], so our final result is
(1, 'A') : (2, 'B') : (3, 'C') : []
which can also be written as
[(1, 'A'), (2, 'B'), (3, 'C')]
You probably already knew that was what the answer would eventually be. I hope now you can see how we get that answer.
If you understand what the three equations make zip do at each step, we can summarise the process like this:
zip [1, 2, 3] ['A', 'B', 'C']
(1, 'A') : (zip [2, 3] ['B', 'C'])
(1, 'A') : (2, 'B') : (zip [3] ['C'])
(1, 'A') : (2, 'B') : (3, 'C') : (zip [] [])
(1, 'A') : (2, 'B') : (3, 'C') : []
If you're still confused, try to put your finger on exactly what part confuses you. (Yeah, easier said than done...)

The key to recursion is to stop worrying about how your language provides support for recursion. You really only need to know three things, which I'll demonstrate using zip as the example.
How to solve the base case
The base case is zipping two lists when one is empty. In this case, we simply return an empty list.
zip _ [] = []
zip [] _ = []
How to break a problem into one (or more) simpler problem(s).
A non-empty list can be split into two parts, a head and a tail. The head is a single element; the tail is a (sub)list. To zip together two lists, we "zip" together the two heads using (,), and we zip together the two tails. Since the tails are both lists, we already have a way to zip them together: use zip!
(As a former professor of mine would say, "Trust your recursion".)
You might object that we can't call zip because we haven't finished defining it yet. But we aren't calling it yet; we are just saying that at some point in the future, when we call this function, the name zip will be bound to a function that zips two lists together, so we'll use that.
zip (x:xs) (y:ys) = let h = (x,y)
t = zip xs ys
in ...
How to put the pieces back together.
zip needs to return a list, and we have our head h and tail t of the new list. To put them together, just use (:):
zip (x:xs) (y:ys) = let h = (x,y)
t = zip xs ys
in h : t
Or more simply, zip (x:xs) (y:ys) = (x,y) : zip xs ys
When explaining recursion, it's usually simplest to start with the base case. However, the Haskell code is sometimes simpler if you can write the recursive case first, because it lets us simply the base case.
zip (x:xs) (y:ys) = (x,y) : zip xs ys
zip _ _ = [] -- If the first pattern match failed, at least one input is empty

Taking a step further back, let's introduce the only recursive function you'll ever need:
fix :: (a -> a) -> a
fix f = f (fix f)
fix computes the fixed point of its argument.
The fixed point of a function is the value that, when you apply the function, you get back the fixed point. For instance, the fixed point of the square function square x = x**2 is 1, since square 1 == 1*1 == 1.
fix doesn't look terribly useful, though, since it looks like it just gets stuck in an infinite loop:
fix f = f (fix f) = f (f (fix f)) = f (f (f (fix f))) = ...
However, as we'll see, laziness lets us take advantage of this infinite stream of calls to f.
Ok, how do we actually make use of fix? Consider this nonrecursive version of zip:
zip' :: ([a] -> [b] -> [(a,b)]) -> [a] -> [b] -> [(a,b)]
zip' f (x:xs) (y:ys) = (x,y) : f xs ys
zip' _ _ _ = []
Given two nonempty lists, zip' zips them together by using the help function f that it receives to zip the tails of its inputs. If either input list is empty, it ignores f and returns an empty list. Basically, we've left the hard work to whoever calls zip'. We'll trust them to provide an appropriate f.
But how do we call zip'? What argument can we pass? This is where fix comes in. Look at the type of zip' again, but this time make the substitution t ~ [a] -> [b] -> [(a,b)]:
zip' :: ([a] -> [b] -> [(a,b)]) -> [a] -> [b] -> [(a,b)]
:: t -> t
Hey, that's the type fix expects! What's the type of fix zip'?
> :t fix zip'
fix zip' :: [a] -> [b] -> [(a, b)]
As expected. So what happens if we pass zip' its own fixed point? We should get back... the fixed point, that is, fix zip' and zip' (fix zip') should be the same function. We still don't really know what the fixed point of zip' is, but just for kicks, what happens if we try to call it?
> (fix zip') [1,2] ['a','b']
[(1,'a'),(2,'b')]
It sure looks like we just found a definition of zip! But how? Let's use equational reasoning to figure out what just happened.
(fix zip') [1,2] ['a','b']
== (zip' (fix zip')) [1,2] ['a','b'] -- def'n of fix
== (1,'a') : (fix zip') [2] ['b'] -- def'n of zip'
== (1,'a') : (zip' (fix zip')) [2] ['b'] -- def'n of fix, but in the other direction
== (1,'a') : ((2,'b') : (fix zip') [] []) -- def'n of zip'
== (1,'a') : ((2,'b') : zip' (fix zip') [] []) -- def'n of fix
== (1,'a') : ((2,'b') : []) -- def'n of zip'
Because Haskell is lazy, the last call to zip' doesn't need to evaluate fix zip', because its value is never used. So fix f doesn't need to terminate; it just needs to provide another call to f on demand.
And in then end, we see that our recursive function zip is simply the fixed point of the nonrecursive function zip':
fix f = f (fix f)
zip' f (x:xs) (y:ys) = (x,y) : f xs ys
zip' _ _ _ = []
zip = fix zip'
Let's briefly use fix to define length and (!!) as well.
length xs = fix go' 0 xs
where go' _ acc [] = acc
go' f acc (_:xs) = f (acc + 1) xs
xs !! n = fix (!!!) xs n
where (!!!) _ [] _ = error "Too big"
(!!!) _ (x:_) 0 = x
(!!!) f (x:xs) n = f xs (n-1)
And in general, a recursive function is just the fixed point of a suitable nonrecursive function. Note that not all functions have a fixed point, though. Consider
incr x = x + 1
If you try to call its fixed point, you get
(fix incr) 1 = (incr (fix incr)) 1
= (incr (incr (fix incr))) 1
= ...
Since incr always needs its first argument, the attempt to calculate its fixed point always diverges. It should be obvious that incr has no fixed point, because there is no number x for which x == x + 1.

Here’s a nice trick to show how to convert normal imperative loops into recursion. Here are the steps:
Make data immutable by not mutating objects (e.g. no x.y = z, only x = x { y = z })
Make variables “nearly immutable” by moving all variable-changes to just before control flow
Change into “goto form”
Work out the set of mutating variables
Add “variable changes” for mutating variables that don’t change at each goto
Replace labels with functions and goto with function (tail) calls
Here is a simple example after step 1 but before anything else (made up syntax)
let sumOfList f list =
total = 0
done = False
while (not done) {
case list of
[] -> done = True
(x : xs) ->
list = xs
total = total + (f x)
}
total
Well this doesn’t really do much other than change variables but there’s one thing we can do for step 2:
let sumOfList f list =
total = 0
done = False
while (not done) {
case list of
[] -> done = True
(x : xs) ->
let y = f x in
list = xs
total = total + y
}
total
Step 3:
let sumOfList f list =
total = 0
done = False
loop:
if not done then goto body else goto finish
body:
case list of
[] ->
done = True
goto loop
(x : xs) ->
let y = f x in
list = xs
total = total + y
goto loop
finish:
total
Step 4: the mutating variables are done, list, and total
Step 5:
let sumOfList f list =
done = False
list = list
total = 0
goto loop
loop:
if not done then
total = total
done = done
list = list
goto body
else
total = total
done = done
list = list
goto finish
body:
case list of
[] ->
done = True
total = total
list = list
goto loop
(x : xs) ->
let y = f x in
done = done
total = total + y
list = xs
goto loop
finish:
total
Step 6:
let sumOfList f list = loop False list 0 where
loop done list total =
if not done
then body done list total
else finish done list total
body done list total =
case list of
[] -> loop True list total
(x : xs) -> let y = f x in loop done list (total + y)
finish done list total = total
We can now clean things up by removing some unused parameters:
let sumOfList f list = loop False list 0 where
loop done list total =
if not done
then body done list total
else finish total
body done list total =
case list of
[] -> loop True list total
(x : xs) -> let y = f x in loop done list (total + y)
finish total = total
And realising that in body done is always False and inlining loop and finish
let sumOfList f list = body list 0 where
body list total =
case list of
[] -> total
(x : xs) -> let y = f x in body list (total + y)
And now we can pull the case into multiple function definitions:
let sumOfList f list = body list 0 where
body [] total = total
body (x : xs) total =
let y = f x in body list (total + y)
Now inline the definition of y and give body a better name:
let sumOfList f list = go list 0 where
go [] total = total
go (x : xs) total = go list (total + f y)

A loop is a function call is a loop. Reentering a loop body with updated loop parameters is the same as reentering a function body in a new recursive call with the updated function parameters. Or in other words, a function call is a goto, and the function name is the label to jump to:
loop_label:
do stuff updating a, b, c,
go loop_label
is
loop a b c =
let a2 = {- .... a ... b ... c ... -}
b2 = {- .... a ... b ... c ... -}
c2 = {- .... a ... b ... c ... -}
in
loop a2 b2 c2
You did say you're comfortable with loops.
Let's give the translations of your example functions in terms of the more primitive construct, case, as defined in the Report:
length xs = go 0 xs
where
go a b = case (a , b) of
( acc , [] ) -> acc
( acc , (_ : xs) ) -> go (acc + 1) xs
so it's the same old plain linear recursion.
Same goes to the other two definitions:
zip a b = case ( a , b ) of
( [] , _ ) -> []
( _ , [] ) -> []
(x : xs , y : ys) -> (x,y) : zip xs ys
(the last one is left as an exercise).

Related

How many elements are the same in two lists, which have duplicate elements

I try to find the number of elements that are the same in two lists. There are duplicate elements in two lists.
What I want:
-- (because there are two 's' in both lists )
duplicateEle "sssf" "ssah" = 2
-- (because there are two 'a' and one 's' in both lists, intotal 3 common elements)
duplicateEle "aass" "aaas" = 3
-- (because there are two 'a' and two 's' in both lists, intotal 4 common elements)
duplicateEle "ssaa" "ssaa" = 4
My strategy is check each element in List1 to see if it is the element in List2.
if each element of the List1 is the element of the List2.
If true, count 1 and delete (Data.List) the corresponding element in the second list.
For example,
input "dddd" "ssdd" output 2 because there are two d in both lists.
First I check if the 1st element in List1 which is d is an element in List2, the result is True, so I delete only one d in List2, count +1, now count is 1.
Then I check if the 2nd element in List1 which is d is an element in List2, the result is also True, so, I delete one d in List2,count +1, now count is 2.
Because there is not any d left in List2, so, the count will stay at 2.
My code is: (wrong)
import Data.List
duplicateEleCount :: [Char] -> [Char] -> Int
duplicateEleCount (x:xs) ys =
let count = if x `elem` ys then do 1 (delete x ys) else 0
in count + duplicateEleCount xs ys
What you wrote is not so Haskelly. Since it's strings, we can sort them, then group:
import Data.List
-- group :: Eq a => [a] -> [[a]] -- Defined in `Data.List'
dupreps :: String -> String -> Int
dupreps a b = r
where
x = group $ sort a
y = group $ sort b
Now we have them both ordered and grouped, we can just advance along the two lists in an obvious way,
r = merge'n'count x y 0
merge'n'count _ [] cnt = cnt
merge'n'count [] _ cnt = cnt
merge'n'count (g:gs) (f:fs) cnt
| head g == head f
= merge'n'count gs fs (cnt + min (length g) (length f))
| head g < head f
= merge'n'count gs (f:fs) cnt
| head g > head f
= merge'n'count (g:gs) fs cnt
So that we have e.g.
> dupreps "aab" "abbc"
2
> dupreps "aab" "aabbc"
3
> dupreps "aabccc" "bbc"
2
The groups g and f in merge'n'count are always non-empty by construction, so using head is OK.
If you just want to find the number of common elements between two lists which have repeated items, you can simply do this:
f x y = length $ nub $ intersect x y
intersect will find the common elements (with repetition*), and nub will get the distinct values from that list.
Note: intersect will only include repetition from the first argument i.e. intersect "ss" "s" will return "ss" but intersect "s" "ss" will return just "s".
EDIT: Based on the clarification, we can use foldl to get the desired outcome like so:
dup x y = fst $ foldl (\acc z -> if z `elem` (snd acc) then ((1 + fst acc), delete z (snd acc)) else acc) (0,y) x
This applies the strategy outlined in the question - if the element is found in current value of second list, increase the count and modify the second list, else do nothing.
I believe, this is what you intended to write?
import Data.List
duplicateEleCount :: [Char] -> [Char] -> Int
duplicateEleCount (x:xs) ys =
let (count, ys') = if x `elem` ys then (1, delete x ys) else (0, ys)
in count + duplicateEleCount xs ys'
duplicateEleCount [] _ = 0
You can't use do like you were trying to do. Remember that all variables in Haskell are immutable, so delete doesn't change the original list, it returns a new one that we will have to pass along to the recursive call.
A note on performance: this function is O(n*m), since we have to traverse the whole second list for every element in the first list. We can sort the lists first and perform something similar to the merge operation from merge sort to bring it down to O(n*log(n) + m*log(m))).
On another note, because of haskell's laziness, we can split the function up to one like this, without losing any performance and gaining flexibility:
import Data.List
duplicateElems :: [Char] -> [Char] -> [Char]
duplicateElems (x:xs) ys =
if x `elem` ys
then x : duplicateElems xs (delete x ys)
else duplicateElems xs ys
duplicateElems [] _ = []
duplicateEleCount xs ys = length $ duplicateElems xs ys

How to create a Infinite List in Haskell where the new value consumes all the previous values

If I create a infinite list like this:
let t xs = xs ++ [sum(xs)]
let xs = [1,2] : map (t) xs
take 10 xs
I will get this result:
[
[1,2],
[1,2,3],
[1,2,3,6],
[1,2,3,6,12],
[1,2,3,6,12,24],
[1,2,3,6,12,24,48],
[1,2,3,6,12,24,48,96],
[1,2,3,6,12,24,48,96,192],
[1,2,3,6,12,24,48,96,192,384],
[1,2,3,6,12,24,48,96,192,384,768]
]
This is pretty close to what I am trying to do.
This current code uses the last value to define the next. But, instead of a list of lists, I would like to know some way to make an infinite list that uses all the previous values to define the new one.
So the output would be only
[1,2,3,6,12,24,48,96,192,384,768,1536,...]
I have the definition of the first element [1].
I have the rule of getting a new element, sum all the previous elements.
But, I could not put this in the Haskell grammar to create the infinite list.
Using my current code, I could take the list that I need, using the command:
xs !! 10
> [1,2,3,6,12,24,48,96,192,384,768,1536]
But, it seems to me, that it is possible doing this in some more efficient way.
Some Notes
I understand that, for this particular example, that was intentionally oversimplified, we could create a function that uses only the last value to define the next.
But, I am searching if it is possible to read all the previous values into an infinite list definition.
I am sorry if the example that I used created some confusion.
Here another example, that is not possible to fix using reading only the last value:
isMultipleByList :: Integer -> [Integer] -> Bool
isMultipleByList _ [] = False
isMultipleByList v (x:xs) = if (mod v x == 0)
then True
else (isMultipleByList v xs)
nextNotMultipleLoop :: Integer -> Integer -> [Integer] -> Integer
nextNotMultipleLoop step v xs = if not (isMultipleByList v xs)
then v
else nextNotMultipleLoop step (v + step) xs
nextNotMultiple :: [Integer] -> Integer
nextNotMultiple xs = if xs == [2]
then nextNotMultipleLoop 1 (maximum xs) xs
else nextNotMultipleLoop 2 (maximum xs) xs
addNextNotMultiple xs = xs ++ [nextNotMultiple xs]
infinitePrimeList = [2] : map (addNextNotMultiple) infinitePrimeList
take 10 infinitePrimeList
[
[2,3],
[2,3,5],
[2,3,5,7],
[2,3,5,7,11],
[2,3,5,7,11,13],
[2,3,5,7,11,13,17],
[2,3,5,7,11,13,17,19],
[2,3,5,7,11,13,17,19,23],
[2,3,5,7,11,13,17,19,23,29],
[2,3,5,7,11,13,17,19,23,29,31]
]
infinitePrimeList !! 10
[2,3,5,7,11,13,17,19,23,29,31,37]
You can think so:
You want to create a list (call them a) which starts on [1,2]:
a = [1,2] ++ ???
... and have this property: each next element in a is a sum of all previous elements in a. So you can write
scanl1 (+) a
and get a new list, in which any element with index n is sum of n first elements of list a. So, it is [1, 3, 6 ...]. All you need is take all elements without first:
tail (scanl1 (+) a)
So, you can define a as:
a = [1,2] ++ tail (scanl1 (+) a)
This way of thought you can apply with other similar problems of definition list through its elements.
If we already had the final result, calculating the list of previous elements for a given element would be easy, a simple application of the inits function.
Let's assume we already have the final result xs, and use it to compute xs itself:
import Data.List (inits)
main :: IO ()
main = do
let is = drop 2 $ inits xs
xs = 1 : 2 : map sum is
print $ take 10 xs
This produces the list
[1,2,3,6,12,24,48,96,192,384]
(Note: this is less efficient than SergeyKuz1001's solution, because the sum is re-calculated each time.)
unfoldr has a quite nice flexibility to adapt to various "create-a-list-from-initial-conditions"-problems so I think it is worth mentioning.
A little less elegant for this specific case, but shows how unfoldr can be used.
import Data.List
nextVal as = Just (s,as++[s])
where s = sum as
initList = [1,2]
myList =initList ++ ( unfoldr nextVal initList)
main = putStrLn . show . (take 12) $ myList
Yielding
[1,2,3,6,12,24,48,96,192,384,768,1536]
in the end.
As pointed out in the comment, one should think a little when using unfoldr. The way I've written it above, the code mimicks the code in the original question. However, this means that the accumulator is updated with as++[s], thus constructing a new list at every iteration. A quick run at https://repl.it/languages/haskell suggests it becomes quite memory intensive and slow. (4.5 seconds to access the 2000nd element in myList
Simply swapping the acumulator update to a:as produced a 7-fold speed increase. Since the same list can be reused as accumulator in every step it goes faster. However, the accumulator list is now in reverse, so one needs to think a little bit. In the case of predicate function sum this makes no differece, but if the order of the list matters, one must think a little bit extra.
You could define it like this:
xs = 1:2:iterate (*2) 3
For example:
Prelude> take 12 xs
[1,2,3,6,12,24,48,96,192,384,768,1536]
So here's my take. I tried not to create O(n) extra lists.
explode ∷ Integral i ⇒ (i ->[a] -> a) -> [a] -> [a]
explode fn init = as where
as = init ++ [fn i as | i <- [l, l+1..]]
l = genericLength init
This convenience function does create additional lists (by take). Hopefully they can be optimised away by the compiler.
explode' f = explode (\x as -> f $ take x as)
Usage examples:
myList = explode' sum [1,2]
sum' 0 xs = 0
sum' n (x:xs) = x + sum' (n-1) xs
myList2 = explode sum' [1,2]
In my tests there's little performance difference between the two functions. explode' is often slightly better.
The solution from #LudvigH is very nice and clear. But, it was not faster.
I am still working on the benchmark to compare the other options.
For now, this is the best solution that I could find:
-------------------------------------------------------------------------------------
-- # infinite sum of the previous using fuse
-------------------------------------------------------------------------------------
recursiveSum xs = [nextValue] ++ (recursiveSum (nextList)) where
nextValue = sum(xs)
nextList = xs ++ [nextValue]
initialSumValues = [1]
infiniteSumFuse = initialSumValues ++ recursiveSum initialSumValues
-------------------------------------------------------------------------------------
-- # infinite prime list using fuse
-------------------------------------------------------------------------------------
-- calculate the current value based in the current list
-- call the same function with the new combined value
recursivePrimeList xs = [nextValue] ++ (recursivePrimeList (nextList)) where
nextValue = nextNonMultiple(xs)
nextList = xs ++ [nextValue]
initialPrimes = [2]
infiniteFusePrimeList = initialPrimes ++ recursivePrimeList initialPrimes
This approach is fast and makes good use of many cores.
Maybe there is some faster solution, but I decided to post this to share my current progress on this subject so far.
In general, define
xs = x1 : zipWith f xs (inits xs)
Then it's xs == x1 : f x1 [] : f x2 [x1] : f x3 [x1, x2] : ...., and so on.
Here's one example of using inits in the context of computing the infinite list of primes, which pairs them up as
ps = 2 : f p1 [p1] : f p2 [p1,p2] : f p3 [p1,p2,p3] : ...
(in the definition of primes5 there).

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.

Every n-th element of a list in the form of a list

I went through a post for this problem but I do not understand it. Could someone please explain it?
Q: Find every n-th element of the list in the form of a list start from the n-th element itself.
everyNth :: Int -> [t] -> [t]
everyNth elt = map snd . filter (\(lst,y) -> (mod lst elt) == 0) . zip [1..]
Also, please explain how pattern matching can be used for this problem. That is using
[]->[]
It's easy to use pattern matching to 'select every nth element' for particular cases of n:
every2nd (first:second:rest) = second : every2nd rest
every2nd _ = []
-- >>> every2nd [1..12]
-- [2,4,6,8,10,12]
every3rd (first:second:third:rest) = third : every3rd rest
every3rd _ = []
-- >>> every3rd [1..13]
-- [3,6,9,12]
every4th (first:second:third:fourth:rest) = fourth : every4th rest
every4th _ = []
-- >>> every4th [1..12]
-- [4,8,12]
For the general case, though, we're out of luck, at least with that particular approach. Patterns like those above will need some definite length to be definite patterns. The composed function you mention starts from the thought that we do know how to find every nth member of [1..], namely if it's a multiple of n
multiple n m = m `mod` n == 0
-- >>> filter (multiple 3) [1..12]
-- [3,6,9,12]
So the solution you are trying to understand zips [1..] with the list
index xs = zip [1..] xs
-- >>> index [1..5]
-- [(1,1),(2,2),(3,3),(4,4),(5,5)]
-- >>> index "hello"
-- [(1,'h'),(2,'e'),(3,'l'),(4,'l'),(5,'o')]
Then it filters out just those pairs whose first element is a multiple of n
every_nth_with_index n xs = filter (\(m,a) -> multiple n m) (index xs)
-- >>> every_nth_with_index 3 [1..12]
-- [(3,3),(6,6),(9,9),(12,12)]
-- >>> every_nth_with_index 3 "stackoverflow.com"
-- [(3,'a'),(6,'o'),(9,'r'),(12,'o'),(15,'c')]
Then it gets rid of the ancillary construction, leaving us with just the second element of each pair:
every_nth n xs = map snd (every_nth_with_index n xs)
-- >>> every_nth 3 [1..12]
-- [3,6,9,12]
-- >>> every_nth 3 "stackoverflow.com"
-- "aoroc"
Retracinging our steps we see that this is the same as
everyNth elt = map snd . filter (\(lst,y) -> (mod lst elt) == 0) . zip [1..]
The notorious fold fan strikes again.
everyNth n xs = foldr go (`seq` []) xs n where
go x r 0 = x : r (n - 1)
go _ r k = r (k - 1)
This is very similar to chepner's approach but it integrates the dropping into the recursion. Rewritten without the fold, it's pure pattern matching:
everyNth n = go n where
go k [] = k `seq` []
go 0 (x : xs) = x : go (n - 1) xs
go k (_ : xs) = go (k - 1) xs
With a little cheating, you can define everyNth using pattern matching. Really, we're abstracting out the part that makes pattern matching difficult, as pointed out in Michael's answer.
everyNth n lst = e (shorten lst)
where shorten = drop (n-1) -- here's the cheat
e [] = []
e (first:rest) = first : e (shorten rest)
If you have never seen Haskell before then this takes a bit of explaining.
everyNth :: Int -> [t] -> [t]
everyNth elt = map snd . filter (\(lst,y) -> (mod lst elt) == 0) . zip [1..]
First, note that the type has two arguments, but the definition has only one. This is because the value returned by everyNth is in fact another function. elt is the Int, and the expression in the second line creates a new function that does the job.
Second, note the "." operators. This is an operator that joins two functions together. It is defined like this:
(f . g) x = f (g x)
Here is an equivalent version of the definition with the second argument made explicit:
everyNth elt xs = map snd (filter (\(lst y) -> (mod lst elt) == 0) (zip xs))
When you see a bunch of functions in a chain linked by "." operators you need to read it from right to left. In my second version pay attention to the bracket nesting. zip [1..] xs is the inner-most expression, so it gets evaluated first. It turns a list like ["foo", "bar"] into [(1, "foo"),(2, "bar")]. Then this is filtered to find entries where the number is a multiple of elt. Finally the map snd strips the numbers back out to return just the required entries.

Split list and make sum from sublist?

im searching for a solution for my Haskell class.
I have a list of numbers and i need to return SUM for every part of list. Parts are divided by 0. I need to use FOLDL function.
Example:
initial list: [1,2,3,0,3,4,0,5,2,1]
sublist [[1,2,3],[3,4],[5,2,1]]
result [6,7,7]
I have a function for finding 0 in initial list:
findPos list = [index+1 | (index, e) <- zip [0..] list, e == 0]
(returns [4,6] for initial list from example)
and function for making SUM with FOLDL:
sumList list = foldl (+) 0 list
But I completely failed to put it together :/
---- MY SOLUTION
In the end I found something completely different that you guys suggested.
Took me whole day to make it :/
groups :: [Int] -> [Int]
groups list = [sum x | x <- makelist list]
makelist :: [Int] -> [[Int]]
makelist xs = reverse (foldl (\acc x -> zero x acc) [[]] xs)
zero :: Int -> [[Int]] -> [[Int]]
zero x acc | x == 0 = addnewtolist acc
| otherwise = addtolist x acc
addtolist :: Int -> [[Int]] -> [[Int]]
addtolist i listlist = (i : (head listlist)) : (drop 1 listlist)
addnewtolist :: [[Int]] -> [[Int]]
addnewtolist listlist = [] : listlist
I'm going to give you some hints, rather than a complete solution, since this sounds like it may be a homework assignment.
I like the breakdown of steps you've suggested. For the first step (going from a list of numbers with zero markers to a list of lists), I suggest doing an explicit recursion; try this for a template:
splits [] = {- ... -}
splits (0:xs) = {- ... -}
splits (x:xs) = {- ... -}
You can also abuse groupBy if you're careful.
For the second step, it looks like you're almost there; the last step you need is to take a look at the map :: (a -> b) -> ([a] -> [b]) function, which takes a normal function and runs it on each element of a list.
As a bonus exercise, you might want to think about how you might do the whole thing in one shot as a single fold. It's possible -- and even not too difficult, if you track through what the types of the various arguments to foldr/foldl would have to be!
Additions since the question changed:
Since it looks like you've worked out a solution, I now feel comfortable giving some spoilers. =)
I suggested two possible implementations; one that goes step-by-step, as you suggested, and another that goes all at once. The step-by-step one could look like this:
splits [] = []
splits (0:xs) = [] : splits xs
splits (x:xs) = case splits xs of
[] -> [[x]]
(ys:yss) -> ((x:ys):yss)
groups' = map sum . splits
Or like this:
splits' = groupBy (\x y -> y /= 0)
groups'' = map sum . splits'
The all-at-once version might look like this:
accumulate 0 xs = 0:xs
accumulate n (x:xs) = (n+x):xs
groups''' = foldr accumulate [0]
To check that you understand these, here are a few exercises you might like to try:
What do splits and splits' do with [1,2,3,0,4,5]? [1,2,0,3,4,0]? [0]? []? Check your predictions in ghci.
Predict what each of the four versions of groups (including yours) output for inputs like [] or [1,2,0,3,4,0], and then test your prediction in ghci.
Modify groups''' to exhibit the behavior of one of the other implementations.
Modify groups''' to use foldl instead of foldr.
Now that you've completed the problem on your own, I am showing you a slightly less verbose version. Foldr seems better in my opinion to this problem*, but because you asked for foldl I will show you my solution using both functions.
Also, your example appears to be incorrect, the sum of [5,2,1] is 8, not 7.
The foldr version.
makelist' l = foldr (\x (n:ns) -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l
In this version, we traverse the list, if the current element (x) is a 0, we add a new element to the accumulator list (n:ns). Otherwise, we add the value of the current element to the value of the front element of the accumulator, and replace the front value of the accumulator with this value.
Step by step:
acc = [0], x = 1. Result is [0+1]
acc = [1], x = 2. Result is [1+2]
acc = [3], x = 5. Result is [3+5]
acc = [8], x = 0. Result is 0:[8]
acc = [0,8], x = 4. Result is [0+4,8]
acc = [4,8], x = 3. Result is [4+3,8]
acc = [7,8], x = 0. Result is 0:[7,8]
acc = [0,7,8], x = 3. Result is [0+3,7,8]
acc = [3,7,8], x = 2. Result is [3+2,7,8]
acc = [5,7,8], x = 1. Result is [5+1,7,8] = [6,7,8]
There you have it!
And the foldl version. Works similarly as above, but produces a reversed list, hence the use of reverse at the beginning of this function to unreverse the list.
makelist l = reverse $ foldl (\(n:ns) x -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l
*Folding the list from the right allows the cons (:) function to be used naturally, using my method with a left fold produces a reversed list. (There is likely a simpler way to do the left fold version that I did not think of that eliminates this triviality.)
As you already solved it, another version:
subListSums list = reverse $ foldl subSum [0] list where
subSum xs 0 = 0 : xs
subSum (x:xs) n = (x+n) : xs
(Assuming that you have only non-negative numbers in the list)

Resources