Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何使折叠基于一个类别执行多个折叠_Haskell_Fold - Fatal编程技术网

Haskell 如何使折叠基于一个类别执行多个折叠

Haskell 如何使折叠基于一个类别执行多个折叠,haskell,fold,Haskell,Fold,我可以将什么运算符传递给折叠变量之一,以允许我对元组列表中按元组项1分组的元组项2求和 那么,假设我有一张清单: [ ('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1) ] [ ('A', 4) , ('B', 4) , ('C', 11) ] 我想列出以下清单: [ ('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1) ] [ ('A', 4) , ('B', 4) , ('

我可以将什么运算符传递给折叠变量之一,以允许我对元组列表中按元组项1分组的元组项2求和

那么,假设我有一张清单:

[ ('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1) ]
[ ('A', 4) , ('B', 4) , ('C', 11) ]
我想列出以下清单:

[ ('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1) ]
[ ('A', 4) , ('B', 4) , ('C', 11) ]
您可以看到它是一个Haskell化的表,因此表的实际表示并不重要;这是获取输入数据并生成我感兴趣的输出的方法。我是Haskell的新人,有C/C++/C#方面的背景。我已经做了足够多的教程来识别折叠在这里的应用,但无法找出似乎需要的子折叠

编辑: 如果这对其他人有帮助,以下是我的解决方案,使用group、foldl1和map,灵感来自ingo的回应:

import qualified Data.List as List

mygroup :: [ (Char,Int) ] -> [ [(Char,Int)] ]
mygroup = List.groupBy (\x y -> fst x == fst y) 

myfold :: [(Char,Int)] -> (Char,Int)
myfold = foldl1 (\x y -> (fst x, snd x + snd y))

mysum :: [(Char,Int)] -> [(Char,Int)]
mysum = map myfold . mygroup
运行时:

*ListSum> mysum [ ('A',1) , ('A',2) , ('B',3) , ('C',4) , ('C',5) ]
[('A',3),('B',3),('C',9)]
mygroup演示如何通过提供等价运算符来创建组。它说,如果两个成员的第一个元组项相同,则它们属于同一组

myfold演示如何对两个元组求和。它使用列表中的第一个元组作为折叠的初始状态,并根据每个元组的第二个项的总和组成一个结果元组

mysum使用map组合这两个函数

我可能会在这方面花更多的时间,看看我是否可以打破对数据模式的依赖,目前数据模式是[(Char,Int)]。我认为这意味着提供groupBy操作符和fold操作符,可能只是编写groupBy、foldl1和map的一个练习。这方面我是新手


我可以因为无积分而获得积分吗?:)

您真正想要的是使用特定的标准对项目进行分组,然后将组折叠起来

实现您给出的示例的最简单方法是使用
Data.map
中的关联映射对项目进行分组

import qualified Data.Map as Map

sumGroups :: [(Char, Int)] -> [(Char, Int)]
sumGroups = Map.assocs . Map.fromListWith (+)
这将使用函数组合具有相同键的项,生成的映射将转换回具有相同键的列表


从概念上讲,您需要两个步骤:

transform [('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1)]
to [('A', [1,3,4]), ('C', [10, 1])]
and further to [('A', 8), ('C', 11)]
帮助您的功能:groupBy、using、fst、map、sum

无意义的乐趣:

import Data.List
import Data.Function
import Control.Arrow

sumGroups = map (fst . head &&& sum . map snd) . groupBy ((==) `on` fst) 

你试过什么吗?fold有点像函数式编程的“goto”:对某些事情很有用,但主要是作为更高级的东西(如和)的垫脚石。@dbaupp:没有。我不知道如何编写fold操作符来执行子fold。@DanielWagner:谢谢,这个建议很好地支持了shang的答案。好的,真漂亮。看到有必要在那里进行分组手术,我有点松了一口气,因为这是我的直觉告诉我的;然而我确信这是我对这个问题的爬虫类命令式分析,我需要知道你是如何做到的。我现在想修改多个关键点,但我想我知道如何用你在这里给我的东西来实现这一点。非常感谢。乐高套件形式的答案;我就要这个了,因为它给了我一些关键词来研究;非常感谢。我想说的是,第一次转换让我感到困惑,因为我知道将折叠映射到转换后的列表就是我所需要的。然而,groupBy看起来很有趣。研究这个反应让我想到了“箭头”和“机器人”()。非常有趣,谢谢。