List 对列表中具有相同snd的所有元素求和Haskell

List 对列表中具有相同snd的所有元素求和Haskell,list,haskell,recursion,List,Haskell,Recursion,我想用Haskell做一个多项式计算器,但我在乘法方面遇到了一些问题。多项式作为系数列表引入,其中第一项对应于x^0,第二项对应于x^1,依此类推 对于乘法,我有一个元组列表,在第一个元素上表示它们所属的系数,在第二个元素上表示相应的系数: [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0) (这样做是为了将每个项目的参考值乘以它所属的系数) 由于这是我进入函数式编程的第一步

我想用Haskell做一个多项式计算器,但我在乘法方面遇到了一些问题。多项式作为系数列表引入,其中第一项对应于x^0,第二项对应于x^1,依此类推

对于乘法,我有一个元组列表,在第一个元素上表示它们所属的系数,在第二个元素上表示相应的系数:

[(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)
(这样做是为了将每个项目的参考值乘以它所属的系数)

由于这是我进入函数式编程的第一步,我在创建一个列表时遇到了一些麻烦,其中第一个元素是上面所示的元组中所有第二个元素的总和,第一个元素是0,第二项应该是上面所示列表中元组中所有第二个元素的总和,第一个元素为1,依此类推

我尝试使用Data.Sequence更新,正如第一个答案中所指出的,但它似乎不会“更新”已创建的数据。Sequence每次都会返回一个新的数据

有没有办法创建一个列表并根据索引更新其内容?我正试图找出如何递归解决这个问题,但我不知道如何做,所以任何帮助将不胜感激

这是解决方案

import Data.List
import Data.Function

combine :: [(Int,Int)] -> [Int]
combine = map (sum . map snd) . groupBy ((==) `on` fst) . sort 
从右到左阅读函数以了解其作用

这里是破碎成更小的部分来理解它

*Main> sort [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[(0,-4),(0,-3),(0,-2),(0,-1),(0,0),(0,1),(0,2),(1,0),(2,-1),(2,1),(3,-2),(4,-3),(4,0)]
这将对列表进行排序,以便具有相同第一个元素的所有对都在一起。之后,您还可以使用
折叠

*Main> groupBy ((==) `on` fst) . sort $ [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[[(0,-4),(0,-3),(0,-2),(0,-1),(0,0),(0,1),(0,2)],[(1,0)],[(2,-1),(2,1)],[(3,-2)],[(4,-3),(4,0)]]
这将使用相同的第一个元素组合所有对

*Main> combine [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[-7,0,0,-2,-3]
现在我们只需要计算列表列表中第二个元素的和。

这里是解决方案

import Data.List
import Data.Function

combine :: [(Int,Int)] -> [Int]
combine = map (sum . map snd) . groupBy ((==) `on` fst) . sort 
从右到左阅读函数以了解其作用

这里是破碎成更小的部分来理解它

*Main> sort [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[(0,-4),(0,-3),(0,-2),(0,-1),(0,0),(0,1),(0,2),(1,0),(2,-1),(2,1),(3,-2),(4,-3),(4,0)]
这将对列表进行排序,以便具有相同第一个元素的所有对都在一起。之后,您还可以使用
折叠

*Main> groupBy ((==) `on` fst) . sort $ [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[[(0,-4),(0,-3),(0,-2),(0,-1),(0,0),(0,1),(0,2)],[(1,0)],[(2,-1),(2,1)],[(3,-2)],[(4,-3),(4,0)]]
这将使用相同的第一个元素组合所有对

*Main> combine [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[-7,0,0,-2,-3]

现在我们只需要计算列表列表中第二个元素的和。

欢迎来到Haskell。在这个世界上,事情是简单不变的。所以你不需要更新,而是每次都创建一个新的不可变结构。我真的需要习惯它,因为我来自Java、Python、C等等,这就像一个全新的地平线。我一直在尝试列表理解,但我找不到一种方法。学习Haskell的第一步是放下你对效率和副本的担忧。稍后,当您了解了正在发生的事情后,您可以再次关注效率问题。欢迎来到Haskell。在这个世界上,事情是简单不变的。所以你不需要更新,而是每次都创建一个新的不可变结构。我真的需要习惯它,因为我来自Java、Python、C等等,这就像一个全新的地平线。我一直在尝试列表理解,但我找不到一种方法。学习Haskell的第一步是放下你对效率和副本的担忧。稍后,当你明白发生了什么时,你可以再次关注效率问题。这正是我想要的!谢谢你的帮助,我每次都必须习惯于构建一个新的结构。我花了很长时间来回答,因为我试图理解代码,我想我已经理解了,但是你的解释让它变得更好。再次感谢你们@Jose_Sunstrider运行时系统并不是每次都会构建一个新的结构。由于不变性,大多数东西都是共享的。此外,编译器还有机会将上述操作融合到一个紧密的循环中,这样中间结构甚至不会被创建。这正是我所寻找的!谢谢你的帮助,我每次都必须习惯于构建一个新的结构。我花了很长时间来回答,因为我试图理解代码,我想我已经理解了,但是你的解释让它变得更好。再次感谢你们@Jose_Sunstrider运行时系统并不是每次都会构建一个新的结构。由于不变性,大多数东西都是共享的。此外,编译器还有机会将上述操作融合到一个紧密的循环中,以便甚至不创建中间结构。