agrupa::Eq a => [a] -> [[a]]
agrupa [] = []
agrupa (h:ts) = if h== (head ts) then [[h:(head ts)]]
else []
错误:
它说*无法匹配预期类型[a]' with actual type
a'in head ts
我没有得到的是他假设头部是[[a]]当它不是,[h :(头部ts)] = [a]
7 | if h== (head ts) then [[h:(head ts)]]
注意: 忽略其他的,只是推迟那里[]有东西
答案 0 :(得分:1)
你写道:
h:(head ts)
现在,“cons”(:) :: a -> [a] -> [a]
获取一个元素(“head”)和一个元素列表(“tail”),并创建一个以头部后跟尾部开头的列表。但由于h
是列表的元素,而head ts
是同一列表的元素,因此它们都具有a
类型。
如果您想构建一个2项列表,可以使用:
[h, head ts]
代替。但话虽如此,这段代码不正确且非常不安全,因为:
ts
有头:它可以是空列表[]
; 解决上述问题的解决方法是:
agrupa :: Eq a => [a] -> [[a]]
agrupa [] = []
agrupa [x] = [[x]]
agrupa (x1:xs@(x2:_)) | x1 == x2 = (x1:y1) : yt
| otherwise = [x1] : ys
where ys@(y1:yt) = agrupa xs
代码的工作方式如下:前两个案例很简单:如果我们将一个空列表分组,我们获得一个空列表,如果我们将一个元素组合在一起,我们就会得到一个包含该单个元素的组。
递归案例更复杂。在这里,我们检查列表x1
和x2
的前两项。如果两者不相等(第二防护),我们就这样构建一个单独的组[x1]
,然后将列表的其余部分agrupa xs
分组。
如果两个元素 相等,我们再次首先对列表(y1:yt) = agrupa xs
的剩余部分执行递归,但我们知道第一个组y1
是相同的x1
值所属的组,否则x1
不应等于x2
。因此,我们通过将x1
添加到其中来修改第一个组。返回(x1:y1) : yt
。
此功能产生:
*Main> agrupa [1,1,2,1,1,4,4,4,5]
[[1,1],[2],[1,1],[4,4,4],[5]]
然而,这个功能仍然可以改进,但我把它留作练习。