Haskell 列表错误的部分和

Haskell partial sum of a list error

我需要在 Haskell 中编写一个函数,对列表的元素求和,直到某些特定元素存储在另一个列表中。

例如partial_add [1,2,3,4,5,6] [2,5] 0应该return[3,12,6].

我已经走到这一步了:

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

(很可能工作不正常)

但是当我尝试运行函数时(它编译正确)我得到这个错误:

No instance for (Num [t0]) arising from a use of `it' 
In a stmt of an interactive GHCi command: print it

知道发生了什么事吗?

根据你的例子,我会写这样的函数:

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]

顺便说一句。我认为您问题中的解决方案似乎无法完全按照您在示例中指定的方式工作(或者我误解了什么):

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]

但它很容易修复以适用于您的示例:

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]

注意:我对 count 参数有点困惑,因为它在其中一个递归调用中被忽略,它总是作为 0 传递。一旦更清楚它的作用,添加它的行为应该很容易。

另一种看待这个问题的方法是首先将第二个列表*分成子列表分隔(并包括)第一个列表的元素然后找到总和每个子列表:

-- | 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]

给予

[3,12,6]

我认为这是 "bottom up" 在 Haskell 中编程的一个很好的例子。

* 我颠倒了参数顺序以匹配 Data.List.Split.

使用的顺序

感谢您的回答,我明白了。 我需要声明函数的类型并将括号放在它们应该出现的位置。 该代码确实无法正常工作,但我已将其修复。

固定代码如下:

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)

它可能不是最好的,但对我来说很有效。