Haskell:将列表列表中的所有内容包装为一个元素的列表列表

Haskell: wrap everything in list of lists as a list of lists of one element

大家好。

我想要完成的是将列表转换为 [ [1, 2, 3], [25, 24, 23, 22], [13] ] 变成 [ [1], [2], [3], [25], [24], [23], [22], [13] ]

我试过

reWrap :: [[a]] -> [[a]]
reWrap data = map (map (:[])) data

当然,它只是将内容更深地包裹在括号中。我是函数式编程的新手,因此非常感谢任何帮助或提示。提前致谢!

也许reWrap = (>>= map return)?但这对于初学者来说可能太深奥了。有一个非常接近您尝试的解决方案:rewrap xs = concat $ map (map (:[])) xs。请注意,您的输出非常接近您想要的,除了所有内容都在列表中太深一层; concat 获取列表列表并将其展平。

我的解决方案实际上是在做同样的事情,只是更多 shorthand。具体来说,(:[]) 只是 return 专用于列表,而 concat $ map f xs 与列表的 xs >>= f 相同。然后我还删除了显式 xs 参数,因为您对它所做的一切就是将它传递给您真正定义的部分应用函数。

首先你需要连接列表

这个[ [1, 2, 3], [25, 24, 23, 22], [13] ] 变成 [1,2,3,25,24,23,22,13]

然后你需要将每个元素包装在一个列表中

reWrap = map (:[]) . concat

这很容易,如果你使用 concatMap 前奏功能:

λ> :t concatMap
concatMap :: (a -> [b]) -> [a] -> [b]

concatMap 所做的是 map 一个函数,然后是 concat 结果列表。

如果我们使用这个定义,我们可以得到想要的效果:

solution :: [[a]] -> [[a]]
solution = concatMap (map (:[]))

这是实际操作:

λ> solution [[1,2,3],[4,5,6]]
[[1],[2],[3],[4],[5],[6]]
λ> solution [[1,2,3],[],[12,19]]
[[1],[2],[3],[12],[19]]

正如@amalloy 所说,列表中的 >>= 函数等同于 flip concatMap,因此您可以这样说:

solution = (=<<) (map (:[]))

这显然是一个很好的旧列表理解的案例:

 rewrap xss = [ [x] | xs <- xss, x <- xs ]

一个递归版本,不是最短的,但它说明了每个嵌套列表中每个项目的包装,并且连接了包装的嵌套列表,

reWrap :: [[a]] -> [[a]]
reWrap [] = [[]]
reWrap (xs:xss) = (map (:[]) xs) ++ reWrap xss