关于Concat方法类型的解释

时间:2018-05-03 07:29:12

标签: haskell concat

有人可以向我解释为什么我的concat实现中的源列表类型不起作用?

conc::[[a]]->[a]
conc xs@(x1:xs')=foldr (:) [] xs

为什么源列表应为[a]而不是[[a]]?如果我想连续[[1,2],[3,4]]不是[[a]]类型而不是[a],而元素类型是[a]

我收到以下错误:

Couldn't match type `a' with `[a]'
      `a' is a rigid type variable bound by
        the type signature for:
          conc :: forall a. [[a]] -> [a]

2 个答案:

答案 0 :(得分:4)

实际上编译器会在错误中显示有用的提示(实际上比您发布的消息低几行)

Expected type: [a]
Actual type: [[a]]

在下面的代码中,参数确实是[[a]]类型,但结果也是类型[[a]],它与类型定义冲突:

conc :: [[a]] -> [a]
conc xs@(x1:xs') = foldr (:) [] xs
代码中的

xs类型为[[a]],您使用foldr对其进行迭代,并将每个[a]类型的元素添加到列表中。因此,您会收到[[a]]类型的列表。

答案 1 :(得分:1)

对于任何foldr (:) [] xs == xs

Truexs。这意味着foldr (:) []是列表上的标识函数。这个事实众所周知,是Haskell绝杀的一部分,以至于foldr (:) []在经验丰富的Haskell程序员的脑海中自动读作id

查看foldr c n的一种方法是将“cons”(即(:))替换为c,将[]替换为n。名单。将(:)替换为(:)而将[]替换为[]显然不会改变任何内容:

[a, b, ..., z]  ==>  a : b : ... : z : []  ==  [a, b, ..., z]

另一方面用(:)替换(++),将输入列表中的所有列表连接成一个:

[a, b, ..., z]  ==>  a ++ b ++ ... ++ z

这是你想要实现的目标。

因此concat foldr的正确实施是foldr (++) []