非常基本,但我发现问题令人沮丧。我正在尝试对列表中的连续元素进行分组:
myList = [1,2,3,4,4,4,5]
变为
myList = [[1],[2],[3],[4,4,4],[5]]
这是我尝试将foldr与累加器一起使用:
print $ foldr (\ el acc -> if el /= head (head acc) then el ++ (head acc) else acc) [['a']] myList
我不明白为什么我收到以下错误:
Couldn't match expected type ‘[a0]’ with actual type ‘Int’
In the expression: 'a'
In the expression: ['a']
In the second argument of ‘foldr’, namely ‘[['a']]’
任何建议都会很棒!
答案 0 :(得分:2)
在列表上写一个折叠要求我们只回答两种情况:K * N
(空列表,或“nil”)和[]
(一个元素后面跟一个列表或“cons”)
列表为空时的答案是什么?让我们说答案也是一个空列表。因此:
x:xs
列表不为空时的答案是什么?这取决于我们已经积累了什么。可以说我们已经积累了一个小组。我们知道群体是非空的。
nilCase = []
如果consCase x ((g11:_):gs)
,我们会将其添加到群组中。否则我们开始一个新的小组。因此:
x == g11
如果我们还没有累积任何群组怎么办?然后我们只创建一个新组。
consCase x ggs@(g1@(g11:_):gs)
| x == g11 = (x:g1):gs
| otherwise = [x]:ggs
我们可以将这三个案例合并为两个:
consCase x [] = [[x]]
然后所需的折叠就是:
consCase x ggs
| g1@(g11:_):gs <- ggs, x == g11 = (x:g1):gs
| otherwise = [x]:ggs
答案 1 :(得分:1)
使用foldr
,应该是:
group :: (Eq a) => [a] -> [[a]]
group = foldr (\x acc -> if head acc == [] || head (head acc) == x then (x:head acc) : tail acc else [x] : acc) [[]]
答案 2 :(得分:1)
您的案例类型为!
,您正在尝试构建[[Char]]
类型的值。我们的基本情况应该是一个空列表,我们将在每个步骤中添加列表元素。
让我们看看你接下来写的匿名函数。请注意,由于基于您在累加器中的当前[[Int]]
的类型,我们将失败(它们必须返回相同类型的值,并且与累加器的类型相同。如果我们将更好,更清洁模式匹配累加器并在每种情况下以不同方式应用函数:
if
当我们遇到基本情况时,我们应该添加包含在列表中的元素:
func :: Eq a => [a] -> [[a]]
func = foldr f []
where f x [] = undefined
f x (b@(b1:_):bs)
| x == b1 = undefined
| otherwise = undefined
接下来,我们将处理非空列表。如果x等于列表头部的下一个头部,我们应该将其添加到该列表中。否则,我们会
f x [] = [[x]]
把这些放在一起,我们有:
f x (b@(b1:_):bs)
| == b1 = (x:b):bs
| = [x]:b:bs
将问题解决后,使用lambda函数更紧凑地重写它会容易得多。请注意,func :: Eq a => [a] -> [[a]]
func = foldr f []
where f x [] = [[x]]
f x (b@(b1:_):bs)
| x == b1 = (x:b):bs
| otherwise = [x]:b:bs
head
只是[[]]
,因此我们可以将空列表案例和相等案例作为一个操作处理。因此,我们可以改写:
[]
但是,此解决方案最终需要使用func :: (Eq a) => [a] -> [[a]]
func = foldr (\x (b:bs) -> if b == [] || x == head b then (x:b):bs else [x]:b:bs) [[]]
,因为我们必须模式匹配累加器的所有版本。