list 展平列表列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9507358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:47:31  来源:igfitidea点击:

Flatten a list of lists

listhaskelltypesabstract

提问by captainpirate

I have to write a function that flattens a list of lists.

我必须编写一个函数来展平列表列表。

For example flatten [] = []or flatten [1,2,3,4] = [1,2,3,4]or flatten [[1,2],[3],4,5]] = [1,2,3,4,5]

例如flatten [] = []flatten [1,2,3,4] = [1,2,3,4]flatten [[1,2],[3],4,5]] = [1,2,3,4,5]

I'm having trouble with the being able to match the type depending on what is given to the flatten function.

我无法根据提供给 flatten 函数的内容来匹配类型。

Here's what I have:

这是我所拥有的:

data A a = B a | C [a] deriving (Show, Eq, Ord)

flatten::(Show a, Eq a, Ord a)=>A a -> A a
flatten (C []) = (C [])
flatten (C (x:xs) ) = (C flatten x) ++ (C flatten xs)
flatten (B a) = (C [a])

From what I can tell the issue is that the ++operator is expecting a list for both of its arguments and I'm trying to give it something of type A. I've added the Atype so the function can either get a single element or a list of elements.

从我可以看出的问题是,++操作员期望它的两个参数都有一个列表,而我正试图给它一些 type A。我添加了A类型,以便函数可以获取单个元素或元素列表。

Does anyone know a different way to do this differently, or explain what I can do to fix the type error?

有谁知道以不同的方式执行此操作的不同方法,或解释我可以做些什么来修复类型错误?

回答by Malin

It's a bit unclear what you are asking for, but flattening a list of list is a standard function called concatin the prelude with type signature [[a]] -> [a].

有点不清楚您在要求什么,但是展平列表列表是concat在 prelude 中调用的标准函数,类型为 signature [[a]] -> [a]

If you make a data type of nested lists as you have started above, maybe you want to adjust your data type to something like this:

如果您按照上面开始的方式创建嵌套列表的数据类型,也许您想将数据类型调整为如下所示:

 data Lists a = List [a] | ListOfLists [Lists a]

Then you can flatten these to a list;

然后你可以将这些扁平化为一个列表;

 flatten :: Lists a -> [a]
 flatten (List xs) = xs
 flatten (ListOfLists xss) = concatMap flatten xss

As a test,

作为测试,

 > flatten (ListOfLists [List [1,2],List [3],ListOfLists [List [4],List[5]]])
 [1,2,3,4,5]

回答by Mike T

Firstly, the A type is on the right track but I don't think it's quite correct. You want it to be able to flatten arbitrarily nested lists, so a value of type "A a" should be able to contain values of type "A a":

首先,A 型走在正确的轨道上,但我认为这不太正确。您希望它能够展平任意嵌套的列表,因此“A a”类型的值应该能够包含“A a”类型的值:

data A a = B a | C [A a]

Secondly, the type of the function should be slightly different. Instead of returning a value of type "A a", you probably want it to return just a list of a, since by definition the function is always returning a flat list. So the type signature is thus:

其次,函数的类型应该略有不同。您可能希望它只返回 a 的列表,而不是返回“A a”类型的值,因为根据定义,该函数始终返回一个平面列表。所以类型签名是这样的:

flatten :: A a -> [a]

Also note that no typeclass constraints are necessary -- this function is completely generic since it does not look at the list's elements at all.

还要注意,不需要类型类约束——这个函数是完全通用的,因为它根本不查看列表的元素。

Here's my implementation:

这是我的实现:

flatten (B a) = [a]
flatten (C []) = []
flatten (C (x:xs)) = flatten x ++ flatten (C xs)

回答by A_P

this one liner will do the job. Although as it was mentioned by Malin the type signature is different:

这一班轮将完成这项工作。尽管正如 Malin 所提到的,类型签名是不同的:

flatten :: [[a]] -> [a]         
flatten xs = (\z n -> foldr (\x y -> foldr z y x) n xs) (:) []

simple test

简单的测试

frege> li = [[3,4,2],[1,9,9],[5,8]]
frege> flatten li
[3,4,2,1,9,9,5,8]