Haskell - Sum up the first n elements of a list - list

I´m new to Haskell.
Let´s say I want to sum up the first n elements of a list with a generated function on my own. I don´t know how to do this with Haskell. I just know how to sum up a whole given list, e.g.
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
In order to sum up the first n elements of a list, for example
take the first 5 numbers from [1..10], which is 1+2+3+4+5 = 15
I thought I could do something like this:
sumList :: Int -> [Int] -> Int
sumList take [] = 0
sumList take (x:xs) = x + take $ sumList xs
But it doesn´t work... What´s wrong?

So you know how to sum up the numbers in a list,
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
and if that list has no more than 5 elements in it, this function will even return the correct result if you indeed intended to sum no more than 5 elements in an argument list. Let's make our expectations explicit by renaming this function,
sumUpToFiveElements :: [Int] -> Int
sumUpToFiveElements [] = 0
sumUpToFiveElements (x:xs) = x + sumUpToFiveElements xs
it won't return the correct result for lists longer than five, but at least the name is right.
Can we fix that? Can we count up to 5? Can we count up to 5 while also advancing along the input list as we do?
sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs
This still isn't right of course. We do now count, but for some reason we ignore the counter. What is the right time to react to the counter, if we want no more than 5 elements? Let's try counter == 5:
sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements 5 [] = 0
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs
But why do we demand the list to also be empty when 5 is reached? Let's not do that:
sumUpToFiveElements :: Int -> [Int] -> Int
sumUpToFiveElements 5 _ = 0 -- the wildcard `_` matches *anything*
sumUpToFiveElements counter [] = 0
sumUpToFiveElements counter (x:xs) = x + sumUpToFiveElements (counter + 1) xs
Success! We now stop counting when 5 is reached! More, we also stop the summation!!
Wait, but what was the initial value of counter? We didn't specify it, so it's easy for a user of our function (that would be ourselves) to err and use an incorrect initial value. And by the way, what is the correct initial value?
Okay, so let's do this:
sumUpToFiveElements :: [Int] -> Int
sumUpToFiveElements xs = go 1 xs -- is 1 the correct value here?
where
go counter _ | counter == 5 = 0
go counter [] = 0
go counter (x:xs) = x + go (counter + 1) xs
Now we don't have that extraneous argument that made our definition so brittle, so prone to a user error.
And now for the punchline:
Generalize! (by replacing an example value with a symbolic one; changing 5 to n).
sumUpToNElements :: Int -> [Int] -> Int
sumUpToNElements n xs = .......
........
Done.
One more word of advice: don't use $ while at the very beginning of your learning Haskell. Use explicit parens.
sumList take (x:xs) = x + take $ sumList xs
is parsed as
sumList take (x:xs) = (x + take) (sumList xs)
This adds together two unrelated numbers, and then uses the result as a function to be called with (sumList xs) as an argument (in other words it's an error).
You probably wouldn't write it that way if you were using explicit parens.

Well you should limit the number of values with a parameter (preferably not take, since
that is a function from the Prelude), and thus limit the numbers.
This limiting in your code is apparently take $ sumList xs which is very strange: in your function take is an Int, and $ will basically write your statement to (x + take) (sumList xs). You thus apparently want to perform a function application with (x + take) (an Int) as function, and sumList xs as argument. But an Int is not a function, so it does not typecheck, nor does it include any logic to limit the numbers.
So basically we should consider three cases:
the empty list in which case the sum is 0;
the number of elements to take is less than or equal to zero, in that case the sum is 0; and
the number of elements to take is greater than 0, in that case we add the head to the sum of taking one element less from the tail.
So a straightforward mapping is:
sumTakeList :: (Integral i, Num n) => i -> [n] -> n
sumTakeList _ [] = 0
sumTakeList t (x:xs) | t <= 0 = 0
| otherwise = x + sumTakeList (t-1) xs
But you do not need to write such logic yourself, you can combine the take :: Int -> [a] -> [a] builtin with the sum :: Num a => [a] -> a functions:
sumTakeList :: Num n => Int -> [n] -> n
sumTakeList t = sum . take t
Now if you need to sum the first five elements, we can make that a special case:
subList5 :: Num n => [n] -> n
sumList5 = sumTakeList 5

A great resource to see what functions are available and how they work is Hoogle. Here is its page on take and the documentation for the function you want.
As you can see, the name take is taken, but it is a function you can use to implement this.
Note that your sumList needs another argument, the number of elements to sum. the syntax you want is something like:
sumList :: Int -> [Int] -> Int
sumList n xs = _ $ take n xs
Where the _ are blanks you can fill in yourself. It's a function in the Prelude, but the type signature is a little too complicated to get into right now.
Or you could write it recursively, with two base cases and a third accumulating parameter (by means of a helper function):
sumList :: Int -> [Int] -> Int
sumList n xs = sumList' n xs 0 where
sumList' :: Int -> [Int] -> Int -> Int
sumList' 0 _ a = _ -- A base case.
sumList' _ [] a = _ -- The other base case.
sumList' m (y:ys) a = sumList' _ _ _ -- The recursive case.
Here, the _ symbols on the left of the equals signs should stay there, and mean that the pattern guard ignores that parameter, but the _ symbols on the right are blanks for you to fill in yourself. Again, GHC will tell you the type you need to fill the holes with.
This kind of tail-recursive function is a very common pattern in Haskell; you want to make sure that each recursive call brings you one step closer to the base case. Often, that will mean calling itself with 1 subtracted from a count parameter, or calling itself with the tail of the list parameter as the new list parameter. here, you want to do both. Don't forget to update your running sum, a, when you have the function call itself recursively.

Here's a short-but-sweet answer. You're really close. Consider the following:
The take parameter tells you how many elements you need to sum up, so if you do sumList 0 anything you should always get 0 since you take no elements.
If you want the first n elements, you add the first element to your total and compute the sum of the next n-1 elements.
sumList 0 anything = 0
sumList n [] = 0
sumList n (e:es) = e + sumList (n-1) e

Related

Breaking a list into sublists of a specified size using foldr

I'm taking a functional programming class and I'm having a hard time leaving the OOP mindset behind and finding answers to a lot of my questions.
I have to create a function that takes an ordered list and converts it into specified size sublists using a variation of fold.
This isn't right, but it's what I have:
splitList :: (Ord a) => Int -> [a] -> [[a]]
splitList size xs
| [condition] = foldr (\item subList -> item:subList) [] xs
| otherwise =
I've been searching and I found out that foldr is the variation that works better for what I want, and I think I've understood how fold works, I just don't know how I'll set up the guards so that when length sublist == size haskell resets the accumulator and goes on to the next list.
If I didn't explain myself correctly, here's the result I want:
> splitList 3 [1..10]
> [[1,2,3],[4,5,6],[7,8,9],[10]]
Thanks!
While Fabián's and chi's answers are entirely correct, there is actually an option to solve this puzzle using foldr. Consider the following code:
splitList :: Int -> [a] -> [[a]]
splitList n =
foldr (\el acc -> case acc of
[] -> [[el]]
(h : t) | length h < n -> (el : h) : t
_ -> [el] : acc
) []
The strategy here is to build up a list by extending its head as long as its length is lesser than desired. This solution has, however, two drawbacks:
It does something slightly different than in your example;
splitList 3 [1..10] produces [[1],[2,3,4],[5,6,7],[8,9,10]]
It's complexity is O(n * length l), as we measure length of up to n–sized list on each of the element which yields linear number of linear operations.
Let's first take care of first issue. In order to start counting at the beginning we need to traverse the list left–to–right, while foldr does it right–to–left. There is a common trick called "continuation passing" which will allow us to reverse the direction of the walk:
splitList :: Int -> [a] -> [[a]]
splitList n l = map reverse . reverse $
foldr (\el cont acc ->
case acc of
[] -> cont [[el]]
(h : t) | length h < n -> cont ((el : h) : t)
_ -> cont ([el] : acc)
) id l []
Here, instead of building the list in the accumulator we build up a function that will transform the list in the right direction. See this question for details. The side effect is reversing the list so we need to counter that by reverse application to the whole list and all of its elements. This goes linearly and tail-recursively tho.
Now let's work on the performance issue. The problem was that the length is linear on casual lists. There are two solutions for this:
Use another structure that caches length for a constant time access
Cache the value by ourselves
Because I guess it is a list exercise, let's go for the latter option:
splitList :: Int -> [a] -> [[a]]
splitList n l = map reverse . reverse . snd $
foldr (\el cont (countAcc, listAcc) ->
case listAcc of
[] -> cont (countAcc, [[el]])
(h : t) | countAcc < n -> cont (countAcc + 1, (el : h) : t)
(h : t) -> cont (1, [el] : (h : t))
) id l (1, [])
Here we extend our computational state with a counter that at each points stores the current length of the list. This gives us a constant check on each element and results in linear time complexity in the end.
A way to simplify this problem would be to split this into multiple functions. There are two things you need to do:
take n elements from the list, and
keep taking from the list as much as possible.
Lets try taking first:
taking :: Int -> [a] -> [a]
taking n [] = undefined
taking n (x:xs) = undefined
If there are no elemensts then we cannot take any more elements so we can only return an empty list, on the other hand if we do have an element then we can think of taking n (x:xs) as x : taking (n-1) xs, we would only need to check that n > 0.
taking n (x:xs)
| n > 0 = x :taking (n-1) xs
| otherwise = []
Now, we need to do that multiple times with the remainder so we should probably also return whatever remains from taking n elements from a list, in this case it would be whatever remains when n = 0 so we could try to adapt it to
| otherwise = ([], x:xs)
and then you would need to modify the type signature to return ([a], [a]) and the other 2 definitions to ensure you do return whatever remained after taking n.
With this approach your splitList would look like:
splitList n [] = []
splitList n l = chunk : splitList n remainder
where (chunk, remainder) = taking n l
Note however that folding would not be appropriate since it "flattens" whatever you are working on, for example given a [Int] you could fold to produce a sum which would be an Int. (foldr :: (a -> b -> b) -> b -> [a] -> b or "foldr function zero list produces an element of the function return type")
You want:
splitList 3 [1..10]
> [[1,2,3],[4,5,6],[7,8,9],[10]]
Since the "remainder" [10] in on the tail, I recommend you use foldl instead. E.g.
splitList :: (Ord a) => Int -> [a] -> [[a]]
splitList size xs
| size > 0 = foldl go [] xs
| otherwise = error "need a positive size"
where go acc x = ....
What should go do? Essentially, on your example, we must have:
splitList 3 [1..10]
= go (splitList 3 [1..9]) 10
= go [[1,2,3],[4,5,6],[7,8,9]] 10
= [[1,2,3],[4,5,6],[7,8,9],[10]]
splitList 3 [1..9]
= go (splitList 3 [1..8]) 9
= go [[1,2,3],[4,5,6],[7,8]] 9
= [[1,2,3],[4,5,6],[7,8,9]]
splitList 3 [1..8]
= go (splitList 3 [1..7]) 8
= go [[1,2,3],[4,5,6],[7]] 8
= [[1,2,3],[4,5,6],[7,8]]
and
splitList 3 [1]
= go [] 1
= [[1]]
Hence, go acc x should
check if acc is empty, if so, produce a singleton list [[x]].
otherwise, check the last list in acc:
if its length is less than size, append x
otherwise, append a new list [x] to acc
Try doing this by hand on your example to understand all the cases.
This will not be efficient, but it will work.
You don't really need the Ord a constraint.
Checking the accumulator's first sublist's length would lead to information flow from the right and the first chunk ending up the shorter one, potentially, instead of the last. Such function won't work on infinite lists either (not to mention the foldl-based variants).
A standard way to arrange for the information flow from the left with foldr is using an additional argument. The general scheme is
subLists n xs = foldr g z xs n
where
g x r i = cons x i (r (i-1))
....
The i argument to cons will guide its decision as to where to add the current element into. The i-1 decrements the counter on the way forward from the left, instead of on the way back from the right. z must have the same type as r and as the foldr itself as a whole, so,
z _ = [[]]
This means there must be a post-processing step, and some edge cases must be handled as well,
subLists n xs = post . foldr g z xs $ n
where
z _ = [[]]
g x r i | i == 1 = cons x i (r n)
g x r i = cons x i (r (i-1))
....
cons must be lazy enough not to force the results of the recursive call prematurely.
I leave it as an exercise finishing this up.
For a simpler version with a pre-processing step instead, see this recent answer of mine.
Just going to give another answer: this is quite similar to trying to write groupBy as a fold, and actually has a couple gotchas w.r.t. laziness that you have to bear in mind for an efficient and correct implementation. The following is the fastest version I found that maintains all the relevant laziness properties:
splitList :: Int -> [a] -> [[a]]
splitList m xs = snd (foldr f (const ([],[])) xs 1)
where
f x a i
| i <= 1 = let (ys,zs) = a m in ([], (x : ys) : zs)
| otherwise = let (ys,zs) = a (i-1) in (x : ys , zs)
The ys and the zs gotten from the recursive processing of the rest of list indicate the first and the rest of the groups into which the rest of the list will be broken up, by said recursive processing. So we either prepend the current element before that first subgroup if it is still shorter than needed, or we prepend before the first subgroup when it is just right and start a new, empty subgroup.

Implementing Haskell's `take` function using `foldl`

Implementing Haskell's take and drop functions using foldl.
Any suggestions on how to implement take and drop functions using foldl ??
take x ls = foldl ???
drop x ls = foldl ???
i've tried these but it's showing errors:
myFunc :: Int -> [a] -> [a]
myFunc n list = foldl func [] list
where
func x y | (length y) > n = x : y
| otherwise = y
ERROR PRODUCED :
*** Expression : foldl func [] list
*** Term : func
*** Type : a -> [a] -> [a]
*** Does not match : [a] -> [a] -> [a]
*** Because : unification would give infinite type
Can't be done.
Left fold necessarily diverges on infinite lists, but take n does not. This is so because left fold is tail recursive, so it must scan through the whole input list before it can start the processing.
With the right fold, it's
ntake :: Int -> [a] -> [a]
ntake 0 _ = []
ntake n xs = foldr g z xs 0
where
g x r i | i>=n = []
| otherwise = x : r (i+1)
z _ = []
ndrop :: Int -> [a] -> [a]
ndrop 0 xs = xs
ndrop n xs = foldr g z xs 0 xs
where
g x r i xs#(_:t) | i>=n = xs
| otherwise = r (i+1) t
z _ _ = []
ndrop implements a paramorphism nicely and faithfully, up to the order of arguments to the reducer function g, giving it access to both the current element x and the current list node xs (such that xs == (x:t)) as well as the recursive result r. A catamorphism's reducer has access only to x and r.
Folds usually encode catamorphisms, but this shows that right fold can be used to code up a paramorphism just as well. It's universal that way. I think it is beautiful.
As for the type error, to fix it just switch the arguments to your func:
func y x | ..... = .......
The accumulator in the left fold comes as the first argument to the reducer function.
If you really want it done with the left fold, and if you're really sure the lists are finite, two options:
ltake n xs = post $ foldl' g (0,id) xs
where
g (i,f) x | i < n = (i+1, f . (x:))
| otherwise = (i,f)
post (_,f) = f []
rltake n xs = foldl' g id xs r n
where
g acc x = acc . f x
f x r i | i > 0 = x : r (i-1)
| otherwise = []
r _ = []
The first counts from the left straight up, potentially stopping assembling the prefix in the middle of the full list traversal that it does carry to the end nevertheless, being a left fold.
The second also traverses the list in full turning it into a right fold which then gets to work counting down from the left again, being able to actually stop working as soon as the prefix is assembled.
Implementing drop this way is bound to be (?) even clunkier. Could be a nice exercise.
I note that you never specified the fold had to be over the supplied list. So, one approach that meets the letter of your question, though probably not the spirit, is:
sillytake :: Int -> [a] -> [a]
sillytake n xs = foldl go (const []) [1..n] xs
where go f _ (x:xs) = x : f xs
go _ _ [] = []
sillydrop :: Int -> [a] -> [a]
sillydrop n xs = foldl go id [1..n] xs
where go f _ (_:xs) = f xs
go _ _ [] = []
These each use left folds, but over the list of numbers [1..n] -- the numbers themselves are ignored, and the list is just used for its length to build a custom take n or drop n function for the given n. This function is then applied to the original supplied list xs.
These versions work fine on infinite lists:
> sillytake 5 $ sillydrop 5 $ [1..]
[6,7,8,9,10]
Will Ness showed a nice way to implement take with foldr. The least repulsive way to implement drop with foldr is this:
drop n0 xs0 = foldr go stop xs0 n0
where
stop _ = []
go x r n
| n <= 0 = x : r 0
| otherwise = r (n - 1)
Take the efficiency loss and rebuild the whole list if you have no choice! Better to drive a nail in with a screwdriver than drive a screw in with a hammer.
Both ways are horrible. But this one helps you understand how folds can be used to structure functions and what their limits are.
Folds just aren't the right tools for implementing drop; a paramorphism is the right tool.
You are not too far. Here are a pair of fixes.
First, note that func is passed the accumulator first (i.e. a list of a, in your case) and then the list element (an a). So, you need to swap the order of the arguments of func.
Then, if we want to mimic take, we need to add x when the length y is less than n, not greater!
So we get
myFunc :: Int -> [a] -> [a]
myFunc n list = foldl func [] list
where
func y x | (length y) < n = x : y
| otherwise = y
Test:
> myFunc 5 [1..10]
[5,4,3,2,1]
As you can see, this is reversing the string. This is because we add x at the front (x:y) instead of at the back (y++[x]). Or, alternatively, one could use reverse (foldl ....) to fix the order at the end.
Also, since foldl always scans the whole input list, myFunc 3 [1..1000000000] will take a lot of time, and myFunc 3 [1..] will fail to terminate. Using foldr would be much better.
drop is more tricky to do. I don't think you can easily do that without some post-processing like myFunc n xs = fst (foldl ...) or making foldl return a function which you immediately call (which is also a kind of post-processing).

Compare elements between two lists - Haskell

This is probably a stupid question, but I've been stuck on this problem for some hours now.. I have made a genetic algorithm but thought that I could try to improve it a bit. I want to make a fitness function that compare two lists of digits and returns a value. If both lists contains a number that is the same and are in the same "place" the function should return + 2. If the lists contains a number that is the same but in the wrong place it should return + 1.
I've made two different functions which both fulfill one of these tasks, but I can't manage to incorperate them into one function. Here are the functions:
samePlace _ [] = 0
samePlace [] _ = 0
samePlace (x:xs) (y:ys)
| x == y = (sP xs ys) + 2
| otherwise = sP xs (ys)
This function returns +2 for every digit that is the same and is in the right place.
notSamePlace [] _ = 0
notSamePlace _ [] = 0
notSamePlace (x:xs) (ys)
| elem x (ys) = (notSamePlace xs ys) + 1
| otherwise = (notSamePlace xs ys)
This function returns + 1 is one of the digits in the first list exists in the second list.
The problem I got is that the same-place function requires to split up the two lists and go through them one digit at a time to compare them while the not-the-same-place function needs to keep the second list intact without splitting it up in a head and tail. Would be so thankful if someone could point me in the right direction on how to go about this problem.
Also, my thought was that this function could improve the time it takes to find the solution in the genetic algorithm. If my solution is to find the string "hello world", my thought is that an individual with the gene "leolh owdrl" should have more fitness than a gene that looks like "hFz%l r0M/z". In my program so far the first gene would have a fitness value of 1 (because the 'space' is the only character in the same place as the targets characters) but the second gene has the 'h' and the 'space' right so it would be given a fitness value of 2. Is this a good thought or not?
Thanks!
Below function uses zip to index every character, which allows to pass the full second list into recursive calls.
places :: String -> String -> Int
places _ [] = 0
places [] _ = 0
places xs ys = zippedPlaces (zip xs [1..length xs]) (zip ys [1..length ys])
zippedPlaces :: [(Char, Int)] -> [(Char, Int)] -> Int
zippedPlaces [] _ = 0
zippedPlaces (x:xs) ys =
let match = filter (\(num, i) -> fst x == num) ys
in case match of
[] -> zippedPlaces xs ys
(a:_) -> (if snd a == snd x then 2 else 1) + zippedPlaces xs ys
Assumes that no list contains duplicates:
place [] _ = 0
place _ [] = 0
place (x:xs) (y:ys) = place xs ys +
if x == y then 1 else (if elem x ys then 2 else 0) + (if elem y xs then 2 else 0)

Haskell Filter Multiples of 3 from a List to a Sublist

I am still trying to grasp the way Haskell and Functional Programming works, and I need help understanding why my function is not working. I am trying to create a function that takes a list of integers as a parameter and filters out/returns a sublist which contains any multiples of 3 from the first list. Here is my code:
module Main where
sublist = []
myFunc :: [Int] -> [Int]
myFunc [] = []
myFunc [t] = do
if t `mod` 3 == 0
then t : sublist
else myFunc []
myFunc (h:t) = do
if h `mod` 3 /= 0
then myFunc t
else do
h : sublist
myFunc t
This only returns a list containing the last value passed to the function, and still sublist = []. Thanks for any advice you can give me in advance.
I think you need to first switch over mentally to functional style.
for example, this is to get even numbers from a list
> filter even [1..10]
[2,4,6,8,10]
without using the existing functions you can implement the same functionality
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' condition (x:xs) = if condition x
then x : filter' condition xs
else filter' condition xs
divisibleBy3 n = mod n 3 == 0
now, your program can be written as
filter' divisibleBy3 inputList

Defining a constant value at begining Haskell function

I have just started learning Haskell and have written two functions, one for lists with even lengths and one for lists odd lengths. This means the 'even' function with [0..7] returns [0,7,2,5,4,3,6,1], and the 'odd' function with [0..8] returns [0,7,2,5,4,3,6,1,8] - these are the results I need.
However I after a lot of work I am still not able to combine them so that just one function works for both lists. Here are the functions and I wondered if more experienced Haskell coders know of a solution.
funcOdd :: [Int] -> [Int]
funcOdd [] = []
funcOdd (x:xs) = take (n+1) ((x*2) : (pred n - x):funcOdd(xs)) where n = length xs
funcEven :: [Int] -> [Int]
funcEven [] = []
funcEven (x:xs) = take (n+1) ((x*2) : (n - x):funcEven(xs)) where n = length xs
You can pattern match to separate the cases
fullFunction theList | even (length theList) = funcEven theList
fullFunction theList = funcOdd theList
when you call fullFunction, it will try the first case, checking if the length of the list is even. If this fails it will fallback to the second case.
Perhaps cleaner this way
func xs = zipWith const (go xs) xs
where go [] = []
go (x:xs) = 2*x : ((length xs)-off-x) : go xs
off = mod (length xs) 2
the only difference I see between the two functions is use of pred n vs n which is replaced with off(set) derived from the length of the original list.
zipWith const ... truncates the result with the length of the original list to replace take (n+1).