为什么它显示此错误:无法将预期类型“[a]”与实际类型“a”匹配?

时间:2017-10-14 10:36:03

标签: haskell

 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)]]

注意: 忽略其他的,只是推迟那里[]有东西

1 个答案:

答案 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

代码的工作方式如下:前两个案例很简单:如果我们将一个空列表分组,我们获得一个空列表,如果我们将一个元素组合在一起,我们就会得到一个包含该单个元素的组。

递归案例更复杂。在这里,我们检查列表x1x2的前两项。如果两者不相等(第二防护),我们就这样构建一个单独的组[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]]

然而,这个功能仍然可以改进,但我把它留作练习。