I need to write a function in Haskell that sums the elements of a list until some specific elements stored in another list.
For example partial_add [1,2,3,4,5,
Given your example, I would write the 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 seems not to work quite the way you specified 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 is easily fixed to work for your example:
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]
Note: I am a bit confused by the count
parameter since it is ignored in one of the recursive calls, where it is always passed as 0
. It should be easy to add its behavior once it's more clear what it does.
Another way to look at this is to first separate the second list* into sublists delimited by (and including) the elements of the first list and then to 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 nice example of "bottom up" programming in Haskell.
* I reversed the argument order to match the order used by Data.List.Split
.
Thank to your answers i figured it out. I needed to declare the type of the function and put the parenthesis where they should be. The code was indeed not working as it should but i fixed that to.
Here is 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 possible but it worked out for me.