Haskell partial sum of a list error

后端 未结 3 1276
时光说笑
时光说笑 2021-01-20 19:32

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,

相关标签:
3条回答
  • 2021-01-20 19:55

    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]
    
    0 讨论(0)
  • 2021-01-20 19:59

    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.

    0 讨论(0)
  • 2021-01-20 20:02

    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.

    0 讨论(0)
提交回复
热议问题