Prelude> :t concat
concat :: Foldable t => t [a] -> [a]
通过查看上面的类型信息,我知道返回的值不是 Foldable 类型类的派生。因此,在下面的代码中,我期望行 dd = concat [cc,aa] 失败,因为cc不是 Foldable 。但是,您可以注意到,它为什么起作用?
Prelude> aa = [1,2]
Prelude> bb=[3,4]
Prelude> cc = concat[aa,bb]
Prelude> dd=concat [cc,aa]
Prelude> dd
[1,2,3,4,1,2]
谢谢!
答案 0 :(得分:6)
concat :: Foldable t => t [a] -> [a]
concat
的阅读方式是折叠列表的集合并返回列表。只要生成的东西是可折叠的,t
就可以代替很多东西。
concat :: [[a]] -> [a]
concat :: ZipList [a] -> [a]
concat :: Set [a] -> [a]
这些都是此功能的所有有效专长。因此,我们可以向其传递一个列表列表,一个列表压缩列表,一组列表或Haskell生态系统中可用的众多其他容器。
现在,就您而言,您将创建列表aa
和bb
。所以 1
aa :: [Int]
bb :: [Int]
现在,正如我们所说,列表是可折叠的,因此[]
是上述类型中t
的有效替代品。那你就
let cc = concat [aa, bb]
您要将列表列表传递给concat
,因此您使用的特定版本是
concat :: [[Int]] -> [Int]
所以cc
的类型是
cc :: [Int]
同样,用[cc, aa]
调用不会造成任何问题,因为您静止会传递列表列表,因此我们使用与以前相同的专业化方法。
dd :: [Int]
我希望这会有所帮助!如果习惯了OOP的“ is-a”风格关系,那么习惯Haskell的基础结构可能会造成混乱。
1 为简单起见,我假设类型为Int
。严格来说,您的变量具有完全Num a => [a]
的类型,可以再次专门用于[Int]
。但是我想您还是会认为它们是整数,所以这不是重点。
答案 1 :(得分:3)
每个列表都是可折叠的;除列表外,还有其他可折叠类型。其他示例包括Vector
和Seq
。 concat
始终返回列表。
concat
的输入为Foldable t => t [a]
。满足Foldable
约束的一种类型是[[Int]]
-(整数列表)的列表。另一个将是Vector [Int]
。内部总是列表,但是外部可以变化。
在两次调用concat
的过程中,您传递一个[[Int]]
-命名的内部列表aa
,bb
,cc
和外部集合[]
在concat
的行中。
cc
与aa
或bb
具有相同的类型。我一直将其写为[Int]
。 GHCi将给出更通用的类型Num a => [a]
,表示您喜欢的任何数字类型的列表a
-Int
,Float
,Double
,{{1 }}。