3

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,6] [2,5] 0 should return [3,12,6].

I have reached this far:

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 probably not working properly)

But when I try to run the function (it compiles properly) 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?

5
  • 3
    Hint: the statement partial_add x list count+a is interpreted as (partial_add x list count)+a not partial_add x list (count+a). Commented Jan 3, 2015 at 14:00
  • Hint2: Check partial_add's type. Then try to add the correct type signature yourself. Commented Jan 3, 2015 at 14:03
  • Thank you everyone! I needed to declare the type partial_add :: [Int] -> [Int] -> Int -> [Int] and add the parenthesis around count+a Commented Jan 3, 2015 at 14:26
  • 3
    @PanosPaparrigopoulos: You can answer your own questions, so don't forget to add an answer later. Commented Jan 3, 2015 at 15:24
  • Note also that the a value gets lost if a `elem` list holds, so you may want to adjust that case. Commented Jan 3, 2015 at 20:10

3 Answers 3

2

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]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @bmk it was indeed not working properly. The second code you posted is what i did to finaly.
1

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.

1 Comment

passing the count as 0 is my way to reset the counter :P don't know if there is a better way but it's only my third day working on haskell and i am a bit influeced by prolog. Thank you for your answer
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.