Partial sum of Haskell list error
I need to write a function in Haskell that sums the elements of a list until some specific elements are stored in another list.
For example partial_add [1,2,3,4,5,6] [2,5] 0
should return [3,12,6]
.
I got to this:
partial_add [] _ count = []
partial_add (a:x) list count | elem a list = count:partial_add x list 0
| otherwise = partial_add x list count+a
(most likely not working as expected)
But when I try to run the function (it compiles correctly) I get this error:
No instance for (Num [t0]) arising from a use of `it'
In a stmt of an interactive GHCi command: print it
Any idea what's going on?
source to share
Given your example, I would write a function something like this:
partialAdd :: [Int] -> [Int] -> [Int]
partialAdd ls seps = foldr f [] ls
where
f a [] = [a]
f a (x:xs)
| a `elem` seps = a:x:xs
| otherwise = (x+a):xs
*Main> partialAdd [1,2,3,4,5,6] [2,5]
[3,12,6]
Btw. I think the solution in your question doesn't seem to work the way you pointed out in your example (or I misunderstood something):
partial_add :: [Int] -> [Int] -> Int -> [Int]
partial_add [] _ count = []
partial_add (a:x) list count | elem a list = count:partial_add x list 0
| otherwise = partial_add x list (count+a)
*Main> partial_add [1,2,3,4,5,6] [2,5] 0
[1,7]
But it's easy for your example to work:
partial_add :: [Int] -> [Int] -> Int -> [Int]
partial_add [] _ count = [count]
partial_add (a:x) list count | elem a list = (count+a):partial_add x list 0
| otherwise = partial_add x list (count+a)
*Main> partial_add [1,2,3,4,5,6] [2,5] 0
[3,12,6]
source to share
Note. I am a bit confused about the parameter count
as it is ignored in one of the recursive calls where it is always passed as 0
. It should be easy to add his behavior when it becomes clearer what he does.
Another way to look at this is to first separate the second list * in the sublists, separated by (and including) the elements of the first list, and then find the sums of each sublist:
-- | A version of Data.List.splitOneOf that includes the delimiter
splitOneOf' :: Eq a => [a] -> [a] -> [[a]]
splitOneOf' _ [] = [[]]
splitOneOf' delims (x:xs) | x `elem` delims = [x] : splitOneOf' delims xs
splitOneOf' delims (x:xs) | otherwise = let (ys:yss) = splitOneOf' delims xs
in (x:ys) : yss
partialAdd :: (Eq a, Num a) => [a] -> [a] -> [a]
partialAdd delims = map sum . splitOneOf' delims
main :: IO ()
main = print $ partialAdd [2,5] [1,2,3,4,5,6]
gives
[3,12,6]
I think this is a good example of bottom-up programming in Haskell.
* I changed the order of the argument to match the order used Data.List.Split
.
source to share
Thanks for your answers, I figured it out. I needed to declare the type of the function and put the brackets where they should be. The code didn't really work as it should, but I fixed it.
Here's the fixed code:
partial_add :: [Int] -> [Int] -> Int -> [Int]
partial_add [] _ count = [count]
partial_add (a:x) list count | elem a list = (count+a):partial_add x list 0
| otherwise = partial_add x list (count+a)
It may not be the best, but it worked for me.
source to share