Haskell部分求和列表错误

时间:2015-01-03 13:56:55

标签: haskell

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

例如partial_add [1,2,3,4,5,6] [2,5] 0应该返回[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

知道发生了什么事吗?

3 个答案:

答案 0 :(得分:2)

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

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]

答案 1 :(得分:1)

注意:我对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]

我认为这是Haskell中“自下而上”编程的一个很好的例子。

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

答案 2 :(得分:0)

感谢您的回答,我想通了。 我需要声明函数的类型并将括号放在它们应该的位置。 代码确实不能正常工作,但我已经解决了这个问题。

这是固定代码:

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)

这可能不是最好的,但它对我有用。