Understanding recursion in Haskell - haskell
I am having a very difficult time understand how to think about problems in a recursive way, and solve them using Haskell. I have spent hours of reading trying to wrap my head around recursion. The explanation I most often get from people who understand it is never clear and is something like "you pass a function, the name of the function as the argument, the function will then execute, solving a small piece of a the problem and calling the function again and again until you hit the base case".
Can someone please be kind enough, and walk me through the thought process of these three simple recursive functions? Not so much the functionality of them, but how the code, ends up executing and solving the problem, recursively.
Many thanks in advance!
Function 1
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:rest) = max x(maximum' rest)
Function 2
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
Function 3
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
Guidelines
When trying to understand recursion, you may find it easier to think about how the algorithm behaves for a given input. It's easy to get hung up on what the execution path looks like, so instead ask yourself questions like:
What happens if I pass an empty list?
What happens if I pass a list with one item?
What happens if I pass a list with many items?
Or, for recursion on numbers:
What happens if I pass a negative number?
What happens if I pass 0?
What happens if I pass a number greater than 0?
The structure of a recursive algorithm is often just a matter of covering the above cases. So let's see how your algorithms behave to get a feel for this approach:
maximum'
maximum [] = error
maximum [1] = 1
maximum [1, 2] = 2
As you can see, the only interesting behaviour is #3. The others just ensure the algorithm terminates. Looking at the definition,
maximum' (x:rest) = max x (maximum' rest)
Calling this with [1, 2] expands to:
maximum [1, 2] ~ max 1 (maximum' [2])
~ max 1 2
maximum' works by returning a number, which this case knows how to process recursively using max. Let's look at one more case:
maximum [0, 1, 2] ~ max 0 (maximum' [1, 2])
~ max 0 (max 1 2)
~ max 0 2
You can see how, for this input, the recursive call to maximum' in the first line is exactly the same as the previous example.
reverse'
reverse [] = []
reverse [1] = [1]
reverse [1, 2] = [2, 1]
Reverse works by taking the head of the given list and sticking it at the end. For an empty list, this involves no work, so that's the base case. So given the definition:
reverse' (x:xs) = reverse' xs ++ [x]
Let's do some substitution. Given that [x] is equivalent to x:[], you can see there are actually two values to deal with:
reverse' [1] ~ reverse' [] ++ 1
~ [] ++ 1
~ [1]
Easy enough. And for a two-element list:
reverse' [0, 1] ~ reverse' [1] ++ 0
~ [] ++ [1] ++ 0
~ [1, 0]
take'
This function introduces recursion over an integer argument as well as lists, so there are two base cases.
What happens if we take 0-or-less items? We don't need to take any items, so just return the empty list.
take' n _ | n <= 0 = []
take' -1 [1] = []
take' 0 [1] = []
What happens if we pass an empty list? There are no more items to take, so stop the recursion.
take' _ [] = []
take' 1 [] = []
take -1 [] = []
The meat of the algorithm is really about walking down the list, pulling apart the input list and decrementing the number of items to take until either of the above base cases stop the process.
take' n (x:xs) = x : take' (n-1) xs
So, in the case where the numeric base case is satisfied first, we stop before getting to the end of the list.
take' 1 [9, 8] ~ 9 : take (1-1) [8]
~ 9 : take 0 [8]
~ 9 : []
~ [9]
In the case where the list base case is satisfied first, we run out of items before the counter reaches 0, and just return what we can.
take' 3 [9, 8] ~ 9 : take (3-1) [8]
~ 9 : take 2 [8]
~ 9 : 8 : take 1 []
~ 9 : 8 : []
~ [9, 8]
Recursion is a strategy to apply a certain function to a set. You apply the function to the first element of that set, then you repeat the process to the remaining elements.
Let's take an example, you want to double all the integers inside a list. First, you think about which function should I use? Answer -> 2*, now you have to apply this function recursively. Let's call it apply_rec, so you have:
apply_rec (x:xs) = (2*x)
But this only changes the first element, you want to change all the elements on the set. So you have to apply the apply_rec to the remaining elements as well. Thus:
apply_rec (x:xs) = (2*x) : (apply_rec xs)
Now you have a different problem. When does apply_rec ends? It ends when you reach the end of the list. In other words [], so you need to cover this case as well.
apply_rec [] = []
apply_rec (x:xs) = (2*x) : (apply_rec xs)
When you reach the end you do not want to apply any function, hence the function apply_rec should "return" [].
Let's see the behavior of this function in a set = [1,2,3].
apply_rec [1,2,3] = (2 * 1) : (apply_rec [2,3])
apply_rec [2,3] = 2 : ((2 * 2) : (apply_rec [3]))
apply_rec [3] = 2 : (4 : ((2 * 3) : (apply_rec []))
apply_rec [] = 2 : (4 : (6 : [])))
resulting in [2,4,6].
Since you probably do not know very well recursion, the best thing is to start with simpler examples than those that you have presented. Take also a look learn recursion and at this Haskell Tutorial 3 - recursion.
You ask about "thought process", presumably of a programmer, not a computer, right? So here's my two cents:
The way to think about writing some function g with recursion is, imagine that you have already written that function. That's all.
That means you get to use it whenever you need it, and it "will do" whatever it is supposed to be doing. So just write down what that is - formulate the laws that it must obey, write down whatever you know about it. Say something about it.
Now, just saying g x = g x is not saying anything. Of course it is true, but it is a meaningless tautology. If we say g x = g (x+2) it is no longer a tautology, but meaningless anyway. We need to say something more sensible. For example,
g :: Integer -> Bool
g x | x<=0 = False
g 1 = True
g 2 = True
here we said something. Also,
g x = x == y+z where
y = head [y | y<-[x-1,x-2..], g y] -- biggest y<x that g y
z = head [z | z<-[y-1,y-2..], g z] -- biggest z<y that g z
Have we said everything we had to say about x? Whether we did or didn't, we said it about any x there can be. And that concludes our recursive definition - as soon as all the possibilities are exhausted, we're done.
But what about termination? We want to get some result from our function, we want it to finish its work. That means, when we use it to calculate x, we need to make sure we use it recursively with some y that's defined "before" x, that is "closer" to one of the simplest defined cases we have.
And here, we did. Now we can marvel at our handiwork, with
filter g [0..]
Last thing is, in order to understand a definition, don't try to retrace its steps. Just read the equations themselves. If we were presented with the above definition for g, we'd read it simply as: g is a Boolean function of a number which is True for 1, and 2, and for any x > 2 that is a sum of its two preceding g numbers.
Maybe the way your are presenting your issue is not the good one, I mean this is not by studding implementation of existing recursive function that you will understand how you can replicate it. I prefer to provide you an alternative way, it could be view as a methodical process which help you yo write standard skeleton of recursive call and then facilitate reasoning about them.
All your example are about list, then the first stuff when you work with list is to be exhaustive, I mean to use pattern matching.
rec_fun [] = -- something here, surely the base case
rec_fun (x:xs) = -- another thing here, surely the general case
Now, the base case could not include recursive otherwise you will surely end up with a infinite loop, then the base case should return a value, and the best way to grasp this value is to look to the type annotation of your function.
For example :
reverse :: [a] -> [a]
Could encourage you to consider the base case as a value of type [a], as [] for reverse
maximum :: [a] -> a
Could encourage you to consider the base case as a value of type a for maximum
Now for the recursive part, as said the function should include a call of herself.
rec_fun (x:xs) = fun x rec_fun xs
with fun to denote the use of another function which are responsible to realize the chaining of recursive call. To help your intuition we can present it as an operator.
rec_fun (x:xs) = x `fun` rec_fun xs
Now considering (again) the type annotation of your function (or more shortly the base case), you should be able to deduce the nature of this operator. For reverse, as its should return a list the operator is surely the concatenation (++) and so on.
If you put all this stuff together, it shouldn't be so hard to end up with the desired implementation.
Of course, as with any other algorithm, you will always need to thinks a little bit and there are no magical recipe, you must think. For example, when you know the maximum of the tail of the list, what is the maximum of the list ?
Looking at Function 3:
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
Let's say you called reverse' [1,2,3] then...
1. reverse' [1,2,3] = reverse' [2,3] ++ [1]
reverse' [2,3] = reverse' [3] ++ [2] ... so replacing in equation 1, we get:
2. reverse' [1,2,3] = reverse' [3] ++ [2] ++ [1]
reverse' [3] = [3] and there is no xs ...
** UPDATE ** There *is* an xs! The xs of [3] is [], the empty list.
We can confirm that in GHCi like this:
Prelude> let (x:xs) = [3]
Prelude> xs
[]
So, actually, reverse' [3] = reverse' [] ++ [3]
Replacing in equation 2, we get:
3. reverse' [1,2,3] = reverse' [] ++ [3] ++ [2] ++ [1]
Which brings us to the base case: reverse' [] = []
Replacing in equation 3, we get:
4. reverse' [1,2,3] = [] ++ [3] ++ [2] ++ [1], which collapses to:
5. reverse' [1,2,3] = [3,2,1], which, hopefully, is what you intended!
Maybe you can try to do something similar with the other two. Choose small parameters. Have success!
I too have always found it hard to think recursively. Going through the http://learnyouahaskell.com/ recursion chapter a few times, then trying to re-implement his re-implementations has helped solidify it for me. Also, generally, learning to program functionally by carefully going through the Mostly Adequate Guide and practicing currying and composition has made me focus on solving the core of the problem then applying it in other ways.
Back to recursion...Basically these are the steps I go through when thinking of a recursive solution:
The recursion has to stop, so think of one or more base cases. These are the case(s) where further calls to the function are no longer necessary.
Think of the simplest non-base case (the recursive case), and think of how you can call the function again in a way that will result in the base case...so that the function doesn't keep calling itself. The key is focusing on the simplest non-base case. That will help your mind wrap around the problem.
So, for example, if you have to reverse a list, the base case would be an empty list or a list of one element. When moving to the recursive case, don't think about [1,2,3,4]. Instead think of the simplest case ([1,2]) and how to solve that problem. The answer is easy: take the tail and append the head to get the reverse.
I'm no haskell expert...I just started learning myself. I started with this which works.
reverse' l
| lenL == 1 || lenL == 0 = l
where lenL = length l
reverse' xs ++ [x]
The guard checks if it's a 1 or 0 length list and returns the original list if it is.
The recursive case happens when the list is not length 0 or 1 and gets the reverse of the tail, appending the head. This happens until the list is 1 or 0 length and you have your answer.
Then I realized you don't need the check for a singleton list, since the tail of a one element list is an empty list and I went to this which is the answer in learnyouahaskell:
reverse' :: [a] -> [a]
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
I hope that helps. At the end of the day, practice makes perfect, so keep trying to solve some things recursively and you'll get it.
Related
Haskell find divisors based on comprehension method
I need a little help understanding a comprehension method function. compdivides :: Integer -> [Integer] compdivides x | x > 0 = [a | a <-[1..div x 2], mod x a == 0] ++ [x] | otherwise = compdivides (abs x) I understand that if x is positive we do the 3rd line otherwise the 4th line. In the third line we check whether mod x a == 0 only then do we do everything else. However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here? Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways? itemTotal :: [(String, Float)] -> [(String, Float)] itemTotal [] = [] itemTotal [x] = [x] I am having some trouble with this as well. I understand that if the list is empty we simply return an empty list. However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing? Thank you so much for the help!
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here? This is a generator of the list comprehension. The list comprehension: [ a | a <- [1 .. div x 2 ], mod x a == 0 ] will evaluate such that a takes each item in the list (so 1, 2, …, x/2), and in case mod x a == 0 (x is dividable by a), it will add a to the list. Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways? It appends x at the end of the list. This is done because a number x is always dividable by itself (x), since the a <- [1 .. div x 2] stops at div x 2, it will never check if x divides x. The function will get stuck in an infinite loop for compdivides 0, so you might want to rewrite the function to cover this case as well. However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing? Yes. Usually a pattern like itemTotal (x : xs) = x : itemTotal xs is used where we thus return a list where x is the first item, and we recurse on the tail of the list xs. Your itemTotal function however only makes a copy of the list for the first two clauses. You thus can simply define itemTotal = id. Likely you will need to rewrite the function to determine the total of the items in the list.
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: Why does my implementation of last work for an empty list?
I'm working through exercises in Graham Hutton's book "Programming in Haskell" and as part of one exercise I've re-implemented Haskell's last function like so: lasst xs = drop (length xs - 1) xs Now this works nicely for a non-empty list: > lasst [1,2,3,4,5] [5] But, surprisingly to me, for an empty list it returns an empty list: > lasst [] [] I'm surprised by this because I would expect (length []) - 1 to be evaluated into -1 and the subsequent evaluation of drop -1 [] to throw. Why does my implementation return an empty list for an empty list, rather than throw an exception?
The Haskell report '10 specifies the the standard Prelude. In this section, we see: drop :: Int -> [a] -> [a] drop n xs | n <= 0 = xs drop _ [] = [] drop n (_:xs) = drop (n-1) xs So for a negative n, it will return the entire list. This makes sense with respect to the documentation of drop: drop n xs returns the suffix of xs after the first n elements, or [] if n > length xs. So the first -1 elements of a list, are no elements at all. This is further covered in one of the examples of drop: drop (-1) [1,2] == [1,2]
drop and take are total functions: they always return something without causing a runtime error, no matter what the (total) arguments are. Their definition makes it so that take k xs ++ drop k xs == xs holds for every k and (finite) xs. Note that k can be negative, or even larger than the length of xs, and the above is still guaranteed. It might be surprising at first, but they have the following behavior. Assume xs = [1,2,3]. Then k take drop ========================== ... -2 [] [1,2,3] -1 [] [1,2,3] 0 [] [1,2,3] 1 [1] [2,3] 2 [1,2] [3] 3 [1,2,3] [] 4 [1,2,3] [] 5 [1,2,3] [] ... Personally, I'm unsure about whether their totality is a good idea. It would make sense for them to cause a runtime error for negative k, or for k larger than the length. Still, that's what Haskell does. (Note in passing that tail xs and drop 1 xs differ when xs=[], because tail is not total.)
Pairs of elements from list
I want to convert [1,2,3,4] to [[1 2] [2 3] [3 4]] or [(1 2) (2 3) (3 4)]. In clojure I have (partition 2 1 [1,2,3,4]). How can I do it in haskell? I suspect there is such function in standard api but I can't find it.
The standard trick for this is to zip the list with it's own tail: > let xs = [1,2,3,4] in zip xs (tail xs) [(1,2),(2,3),(3,4)] To see why this works, line up the list and its tail visually. xs = 1 : 2 : 3 : 4 : [] tail xs = 2 : 3 : 4 : [] and note that zip is making a tuple out of each column. There are two more subtle reasons why this always does the right thing: zip stops when either list runs out of elements. That makes sense here since we can't have an "incomplete pair" at the end and it also ensures that we get no pairs from a single element list. When xs is empty, one might expect tail xs to throw an exception. However, because zip checks its first argument first, when it sees that it's the empty list, the second argument is never evaluated. Everything above also holds true for zipWith, so you can use the same method whenever you need to apply a function pairwise to adjacent elements. For a generic solution like Clojure's partition, there is nothing in the standard libraries. However, you can try something like this: partition' :: Int -> Int -> [a] -> [[a]] partition' size offset | size <= 0 = error "partition': size must be positive" | offset <= 0 = error "partition': offset must be positive" | otherwise = loop where loop :: [a] -> [[a]] loop xs = case splitAt size xs of -- If the second part is empty, we're at the end. But we might -- have gotten less than we asked for, hence the check. (ys, []) -> if length ys == size then [ys] else [] (ys, _ ) -> ys : loop (drop offset xs)
Just to throw another answer out there using a different approach: For n=2 you want to simply zip the list with its tail. For n=3 you want to zip the list with its tail and with the tail of its tail. This pattern continues further, so all we have to do is generalise it: partition n = sequence . take n . iterate tail But this only works for an offset of 1. To generalise the offsets we just have to look at the genrated list. It will always have the form: [[1..something],[2..something+1],..] So all left to do is select every offsetth element and we should be fine. I shamelessy stole this version from #ertes from this question: everyNth :: Int -> [a] -> [a] everyNth n = map head . takeWhile (not . null) . iterate (drop n) The entire function now becomes: partition size offset = everyNth offset . sequence . take size . iterate tail
Sometimes is best to roll your own. Recursive functions are what gives LisP its power and appeal. Haskell tries to discourage them but too often a solution is best achieved with a recursive function. They are often quite simple as is this one to produce pairs. Haskell pattern matching reduces code. This could easily be changed by changing only the pattern to (x:y:yys) to produce (a,b), (c,d), (e,f). > prs (x:yys#(y:_)) = (x,y):prs yys > prs "abcdefg" [('a','b'),('b','c'),('c','d'),('d','e'),('e','f'),('f','g')
Haskell Increment by One
Trying to create a Haskell program that increments every number in a list by one. module Add1List where add1_list_comp :: [Integer] -> [Integer] add1_list_comp [x] = [x + 1| x <- [x]] It works when I call this add1_list_comp [3] ... it gives me [4] But when I do add1_list_comp [3, 4, 5] ... it throws me an error saying "non-exhaustive patterns in function add1_list_comp" Any help would be much appreciated!
add1_list_comp = map succ that simple or, in your way add1_list_comp xs = [x + 1| x <- xs] the problem with your code is that add1_list_comp [x] does pattern match on list with single item, that's why it fails on list with several items.
I see that the question has been answered, but perhaps I can explain a bit more. The argument of a function is pattern matched, and the general rules are (x:xs) x is the head of the list and xs is the tail of the list, and potentially empty list [] empty list [x] or (x:[]) are the same which is a list with only one variable and a name with no constructor such as "[]", ":", "(,)" around can match anything, so if you want to match a special case, you should put the special case in front of the general pattern. length [] = 0 length [x] = 1 length (x : xs) = 1 + length xs BTW, generally speaking, there will always be a higher order function when you want to do something with a list. for your case add1 xs = map (+1) xs is nicer and it took advantage of the built in library, and you can also do a point free version of it add1 = map (+1)
Well actually since the topic states "Increment by One" without defining what type is going to be incremented by one, just for the sake of a visitor ended up here lets give a solution which would increment any functor by one, which of course includes the list type. So; List functor *Main> fmap (+1) [1,2,3] [2,3,4] Maybe functor (id applies to Nothing) *Main> fmap (+1) (Just 1) Just 2 Either functor (id applies to Left _) *Main> fmap (+1) (Right 2) Right 3 IO functor *Main> fmap ((+1) . read) getLine 2017 2018