2012-02-29 43 views
5

Tengo que escribir una función que aplana una lista de listas.Aplanar una lista de listas

Por ejemplo flatten [] = [] o flatten [1,2,3,4] = [1,2,3,4] o flatten [[1,2],[3],4,5]] = [1,2,3,4,5]

Tengo problemas con el poder para que coincida con el tipo en función de lo que se da a la función aplanar.

Esto es lo que tengo:

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]) 

De lo que puedo decir la cuestión es que el operador ++ está a la espera de una lista de sus dos argumentos y estoy tratando de darle algo de tipo A. Agregué el tipo A para que la función pueda obtener un solo elemento o una lista de elementos.

¿Alguien conoce una manera diferente de hacer esto de manera diferente, o explica qué puedo hacer para corregir el error de tipo?

+0

No estoy seguro de qué es exactamente lo que desea. Tal vez 'aplastar :: A [a] -> A a; aplanar (B xs) = C xs; aplanar (C xss) = C (concat xss) '¿te ayudaría?Básicamente, no puede escribir aplanar para que tome listas de diferentes anidamientos y haga cosas diferentes con ellos, a menos que los ajuste a un nuevo tipo y distinga los casos por constructor. –

+1

El tipo de su función debe ser '[[a]] -> [a]'. Esto significa que 'flatten []' es válido, y 'flatten [[1,2,3,4]]' es válido, pero 'flatten [1,2,3,4]' no lo es. '[1,2,3,4]' no es una lista de listas. Si piensas en eso y comienzas desde el principio, eliminando tu tipo especial, lo encontrarás mucho más fácil. –

+0

posible duplicado de [operación en la lista de listas | cómo] (http://stackoverflow.com/questions/9477806/operation-on-list-of-lists-how) – rampion

Respuesta

20

No está nada claro qué está pidiendo, pero al alisar una lista de lista hay una función estándar llamada concat en el preludio con la firma de tipo [[a]] -> [a].

Si comete un tipo de datos de listas anidadas como haya comenzado anteriormente, tal vez usted quiere ajustar el tipo de datos a algo como esto:

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

Entonces puede acoplar a una lista éstas;

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

Como prueba,

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

En primer lugar, el tipo A está en el camino correcto, pero no creo que sea del todo correcto. Usted quiere que sea capaz de aplanar listas arbitrariamente anidadas, por lo que un valor de tipo "A un" debe ser capaz de contener valores de tipo "A un":

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

En segundo lugar, el tipo de la función debe ser ligeramente diferente. En lugar de devolver un valor de tipo "A a", probablemente desee devolver solo una lista de a, ya que por definición la función siempre devuelve una lista plana. Por lo que el tipo de firma es así:

flatten :: A a -> [a] 

También tenga en cuenta que no hay restricciones de clase de tipos son necesarios - esta función es totalmente genérico, ya que no toma en cuenta los elementos de la lista en absoluto.

Aquí está mi aplicación:

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

'aplanar (B a) = [a]; aplanar (C xs) = aplanar = << xs ' – luqui

0

éste forro hará el trabajo. Aunque como se mencionó por Malin del tipo de firma es diferente:

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

prueba simple

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

El punto es que la función debería funcionar para listas simples y anidadas. Tu trabajo solo para listas simples. – Lii