sum :: [Int] -> Int
sum [] = 0
sum (x:xs) = x + sum xs
I do not understand what the purpose of the line sum [] = 0 is. I found this piece of code in a textbook (it did not go into detail as to what this line does.)
sum [] = 0 is the edge condition of the recursion.
Suppose we have sum [1, 4, 6, 8]. The list can be rewritten as 1:4:6:8:[]. The empty list is the last 'element'. The calculation is as follow (1 + ( 4 + (6 + ( 8 + 0)))). When all the elements of the list have been traversed, what remains is the empty list. Adds zero to the calculated result and ends the iteration.
Related
I'm working on an assignment to calculate the sum of all integers in a list. I am supposed to do so without help from any standard library functions other than the standard addition operator.
I assume this means I cannot use length. I'm understanding that correct, right? This becomes and issue as I'm not sure how I'd know when to stop my recursive function to iterate through the array.
The input's a should be expected to deal with are [] and [0-X] where x is any integer. The example has X as 10, so don't expect anything huge to be tested.
The assignment mentioned it should be in the following format, but I'm not sure I follow:
sum1 [] = ...
sum1 (x:xs) = ...
Here's what I have utilizing length. It works correctly, and I don't really care if it's inefficient. It's my first time using Haskell:
iterate_list :: [Int] -> Int -> Int -> IO()
iterate_list func_list index total = do
if index < length func_list
then do
let new_total = total + (func_list !! index)
let new_index = index + 1
iterate_list func_list new_index new_total
else
print(total)
sum1 :: [Int] -> IO()
sum1 list = do
if length list < 1
then do
print(0)
else
iterate_list list 0 0
update: Based on comments, here is the code I've produced.
total :: Int
total = 0
sum1 :: [Int] -> IO()
sum1 (x:xs) = do
if xs == []
then do
print(total)
else do
let total = total + x
sum1 xs
However, the issue I'm having now is total returns 0, almost like it's a constant. I might be programming it that way, but I'm not too sure what's going on.
Based on the assignment description, I cannot pass a variable through the recursive function to store this value. I've done it that way before. Does anyone know if there is a way to have a "total" variable outside of the function.
total :: Int
total = 0
sum1 :: [Int] -> IO()
sum1 (x:xs) = do
if xs == []
then do
print(total)
else do
let total = total + x
sum1 xs
What this code says:
The global total is a constant integer, equal to 0
sum1 takes a list of integers and produces an IO action that produces no result
If sum1 is given a non-empty list, then:
If the tail of that list is empty (i.e., the whole list has 1 element), then print the global variable total
Otherwise:
Create a new local variable named total, hiding the global one, and define it as x plus itself (an infinite loop)
Recursively call sum1 on the tail of the list
If sum1 is given an empty list, it will throw an error
This shows that you’re thinking very imperatively. Rather than trying to define a bottom-up procedure for updating the total incrementally until it builds up to the final result, you need to think in terms of how to compute the total as a value by breaking down the input. Variables in Haskell are immutable; when you write =, it means equal, never “assign” or “update”.
First, sum1 should return Int because you don’t need IO or do notation for this.
sum1 :: [Int] -> Int
If you want to print the result of sum1 applied to some list someList (for example from main), use print there, i.e., print (sum1 someList).
Next, the function should be defined in terms of the the two possible cases of the input: an empty list and a non-empty list.
sum1 [] = …
sum1 (x : xs) = …
You need to define these cases so that an input like sum1 [1, 2, 3, 4], which you’ll recall is syntactic sugar for sum1 (1 : (2 : (3 : (4 : [])))) produces something equivalent to 1 + 2 + 3 + 4.
First, in the case of an empty list, what should the result be? You can deduce this from the fact that the sum of two lists appended together should be the same as the sum of each of them separately; that is, for any lists xs and ys, these expressions should produce the same result:
sum1 xs + sum1 ys
sum1 (xs ++ ys)
Supposing xs or ys is empty, it should not change the sum:
sum1 [] + sum1 ys = sum1 ([] ++ ys) = sum1 ys
sum1 xs + sum1 [] = sum1 (xs ++ []) = sum1 xs
Second, as for the non-empty case: you’re given an element x :: Int and a list xs :: [Int], and you need to compute the total of the two. For example, given [1, 2, 3, 4], x is set to 1 and xs is [2, 3, 4]. Suppose you had the sum of xs already; what is the result in terms of that and x? And how can you obtain the sum of xs?
You cannot simply update a variable in Haskell. All values are immutable. You should be thinking in terms of how to use the return value of a recursive call, not simply calling a function for its side effect.
The hint from your original question was to define
sum [] = ...
sum (x:xs) = ...
First, what is the sum of the non-empty list? It must include x, so you'll be adding something to x:
sum (x:xs) = x + ...
Second, what is the sum of an empty list? While it might not make sense to even define a value for an empty list, think about what sum [3] must surely return, and the fact that sum (3:[]) == 3 + .... There's a rather simple definition for sum [] that is almost dictated by the definition of addition.
My question is :
I have a list and a number and I want to sum the number to the list so I can do this
Adding ls n = [x+n| x<-ls]
and it works.
My question is I want to add n+1, n+2, n+3 depending of the length of the list.
If I do
let b = 0
Adding´ ls n = [x+adder n b| x<-ls] where adder n b= n+b,b++
it doesn't work because the b doesn't advance, so if I have Adding´ [1,3,4] 3 = [4,7,9] .
You may use Data.List.mapAccumL (mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)) to achieve this task.
The first parameter is a function which takes two parameters a (accumulator) and n (the list item) and returns a tuple. In our case we increment a (the accumulator) by 1 and map the current element n by adding the accumulator. The result is a tuple in which the first item is the final state of the accumulator and the second is the final state of the list. We extract the second item by snd.
Prelude> snd $ Data.List.mapAccumL (\a n -> (a+1,n+a)) 3 [1,3,4]
[4,7,9]
Approach the problem recursively. Add a number to the first element of the list, then recurse on the tail of the list with the next larger number. Repeat until you are out of numbers. Instead of incrementing b, you start a new function call in which b has a larger value.
adding [] _ = []
adding (x:xs) b = x + b : adding xs (b+1)
As an example, consider
adding [7, 10, 7, 5] 0 == 7 + 0 : adding [10, 7, 5] 1
== 7 : (10 + 1 : adding [7, 5] 2)
== 7 : 11 : (7 + 2 : adding [5] 3)
== 7 : 11 : 9 : (5 + 3 : adding [] 4)
== 7 : 11 : 9 : 8 : []
== [7, 11, 9, 8]
You can replace 0 with any starting value n in the initial call; the recursive call always increments it.
Haskell allows to represent recurrent functions in a very concise way. For example, infinite list, that contains Fibonacci numbers can be defined as follows:
fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
I am dealing with 'probabilists' Hermite polynomials, which have the following recursion relation:
What would be the optimal way to construct the infinite list of n-th Hermite polynomials for given x?
We can write it as:
hermite :: (Enum n, Num n) => n -> [n]
hermite x = s
where s#(_:ts) = 1 : x : zipWith3 (\hn2 hn1 n1 -> x*hn1 - n1*hn2) s ts [1..]
where the first items 1 : x : ... are the first elements of the hermite (you can fill in other values).
For the next one, we zip the original values s (so that starts with H0), the tail ts of s (that starts with H1) and the index (that starts with 2, 3, ...) and perform an operation x*hn1 - x*hn2 (nh1 stands for Hn-1, and nh2 stands for Hn-2), and so we calculate the next element each time.
The first 11 values for x = 0.75 are:
Prelude> take 11 (hermite 0.75)
[1.0,0.75,-0.4375,-1.828125,-5.859375e-2,7.2685546875,5.744384765625,-39.30303955078125,-69.68797302246094,262.1583366394043,823.8105096817017]
So the first value is 1, the second x, the third one x*x-2, the fourth one x*x*x-2*x-3*x, and so on.
That being said, if I recall correctly, the recursion formula of the Hermite polynomials is:
Hn(x) = 2×x×Hn-1(x)-2×(n-1)Hn-2(x)
instead of the one quoted in the question.
In that case the formula is thus:
hermite :: (Enum n, Num n) => n -> [n]
hermite x = s
where s#(_:ts) = 1 : 2 * x : zipWith3 helper s ts [1..]
helper hn2 hn1 n1 = 2 * (x * hn1 - n1 * hn2)
Then the first 11 values are:
Prelude> take 11 (hermite 0.75)
[1.0,1.5,0.25,-5.625,-9.9375,30.09375,144.515625,-144.3515625,-2239.74609375,-1049.994140625,38740.4384765625]
Which is correct acording to this Wolfram article:
H0 = 1
H1 = 2*x
H2 = 4˙x2 - 2
H3 = 8˙x3 - 4˙x
H4 = 16˙x4 - 48˙x2 + 12
Which maps exactly on the values we obtained:
Prelude> let x = 0.75 in [1,2*x,4*x*x-2,8*x*x*x-4*x,16*x*x*x*x-48*x*x+12]
[1.0,1.5,0.25,0.375,-9.9375]
I have some Haskell code and need to write down Leftmost-innermost (call by value) and outermost (call-by-name):
second :: [Int] -> Int
second [] = 0
second (_:[]) = 0
second (_:x:xs) = x
doubleEach :: [Int] -> [Int]
doubleEach [] = []
doubleEach (x:xs) = x * 2 : (doubleEach xs)
repeat :: Int -> Int -> [Int]
repeat x n = if n > 0 then x : (repeat x (n-1)) else []
repeat ( second (doubleEach [2,3,5] )) ( second [3, 1, 4] )
innermost (call-by-value):
1. repeat (second (doubleEach [2,3,5] )) (second [3,1,4])
2. repeat (second 4 : doubleEach [3,5])) (1)
3. repeat (second (4 : 6 : d [5])) (1)
4. repeat (second ( 4 : 6 : 10 )) (1)
5. repeat (6) (1)
6. [6]
Question: How can I get outermost (call-by-name) stept by step evaluation? I do not understand how I can do that if repeat needs specified values to work and they are not given until the inner part is not evaluated.
How can I get outermost (call-by-name) stept by step evaluation? I do not understand how I can do that if repeat needs specified values to work and they are not given until the inner part is not evaluated.
You don't need the values to expand the function call - you can just pass in the unevaluated expressions. And then you only evaluate those expressions when it's necessary for ifs, pattern matches or primitive functions. That's how call-by-name evaluation works.
So your first step would be to take the body of repeat, replace each occurrence of x with second (doubleEach [2,3,5]) and each occurrence of n with second [3, 1, 4]. Then you'll need to evaluate the if condition and then you proceed with the body of the if.
I started to play a bit with Haskell and came across the following implementation of the sum function:
sum [] = 0
sum (x:xs) = x + sum xs
And then there's an explanation that shows how the function would behave on a real example:
sum [1,2,3]
1 + (sum [2,3])
1 + (2 + sum [3])
1 + (2 + (3 + sum []))
1 + (2 + (3 + 0))
= 6
I don't understand, why every time sum [x] is called, the list gets smaller by 1 element?
My only assumption is that when the construction (x:xs) is executed, then the element x of the list, not only is retrieved, but also removed (similar to the stacks pop() method.), but I am not sure about this.
In the notation x:xs, x is the head of the list, which is 1 item, and xs is the tail of the list, which is a list of 0 or more items.
Since the recursive call is on xs, the problem size set gets reduced by 1 with each level of recursion.
There's no such a thing as "removing an element from a list". Lists are immutable, just like any other object. Now, with regards to the implementation, in:
sum (x:xs) = x + sum xs
you are pattern matching a list into it's head x and the rest of the list (without the head) xs. Specifically, in sum [1, 2, 3], then you would get:
sum (1:[2, 3]) = 1 + sum [2, 3]
If you remember, (:) is used to append an element to a list. So: 1:[2, 3] is actually [1, 2, 3] which can also be written as: 1:2:3:[].
The only thing that you should remember is that pattern matching on (x:xs), means: put the head of a list in x and the rest of the list in xs.
It's recursion
Basically, you're calling the function again with the rest of the list summed with the first element.