身份很明显,
[ E | P <- (xs ++ ys), Q ] === [ E | P <- xs, Q ] ++ [ E | P <- ys, Q ]
[ x | xs <- [E], x <- xs ] === [ x | x <- E ]
[ x | x <- [E] ] === [E]
我们可以按照代码,
concat [[1,2,3], [4], [5]]
= {- by definition of `concat` -}
[x | xs <- [[1,2,3], [4], [5]], x <- xs]
= {- by definition of `++` -}
[x | xs <- [[1,2,3]] ++ [[4], [5]], x <- xs]
= {- by the first identity -}
[x | xs <- [[1,2,3]], x <- xs] ++ [x | xs <- [[4], [5]], x <- xs]
= {- by the second identity -}
[x | x <- [1,2,3] ] ++ [x | xs <- [[4], [5]], x <- xs]
= {- by definition of `++` -}
[x | x <- [1,2,3] ] ++ [x | xs <- [[4]] ++ [[5]], x <- xs]
= {- by the first identity -}
[x | x <- [1,2,3]] ++ [x | xs <- [[4]], x <- xs] ++ [x | xs <- [[5]], x <- xs]
= {- by the second identity -}
[x | x <- [1,2,3]] ++ [x | x <- [4] ] ++ [x | x <- [5] ]
= {- and by the third -}
[x | x <- [1,2,3]] ++ [ 4 ] ++ [ 5 ]
= {- repeating as before -}
[x | x <- [1]] ++ [x | x <- [2]] ++ [x | x <- [3]] ++ [4] ++ [ 5 ]
= {- by the third identity -}
[ 1 ] ++ [ 2 ] ++ [ 3 ] ++ [4] ++ [ 5 ]
= {- by definition of `++` -}
[ 1 , 2 , 3 , 4 , 5 ]
因此concat,当应用于列表列表时,具有“打开”并消除其中的内括号的效果。
在这个过程中我们也发现了另一个身份,
[ x | x <- Q ] === Q
从上面的那些和++的属性得出,其中
[A,B,C,...,Z] === [A] ++ [B] ++ [C] ++ ... ++ [Z]
另见: