2012-03-21 14 views
8

Así que querían hacer una función de cadena inversa simple en Haskellpatrón de Haskell juego la primera sección, media y última

swapReverse :: String => String 
swapReverse [x] = [x] 
swapReverse [x,y] = [y,x] 
swapReverse (x:xs:l) =   -- pattern match fails here 
    let last = [l] 
     middle = xs 
     first = [x] 
    in last ++ swapReverse middle ++ first 

Entonces, ¿hay una manera de definir una estructura de patrón en Haskell que tiene first y last elemento, y todos los elementos en el middle?

+2

Tenga cuidado con la declaración de tipo :) Probablemente quiso decir 'swapReverse :: String -> String', o tal vez algo más general como' swapReverse :: [a] -> [a] '. –

+0

Por cierto, encontrar el último elemento de una lista vinculada es O (N). Casi nunca realmente quieres hacer eso. – hugomg

+0

La firma de tipo debe ser 'String -> String', BTW – Landei

Respuesta

6

No, no puedes. ¿Por qué? Porque el patrón coincide con los valores de coincidencia y sus subpartes, pero el "medio" de una lista no es una subparte de la lista. La lista [1, 2, 3, 4] es 1:(2:(3:(4:[]))), en términos de su estructura. Por lo tanto, desea hacer coincidir first con 1 y last con 4, que son subpartidas de la lista y, por lo tanto, no descalificadas. Pero el middle que desea sería 2:(3:[]), que no es una subparte de la lista, y por lo tanto, no puede ser una coincidencia.

Tenga en cuenta que tampoco podemos escribir un patrón para que coincida con el primero y el último elemento de una lista. Un patrón tiene una profundidad que se fija en el tiempo de compilación.

5

patrón coincidente funciona en constructores, : es la única lista constructor de lo que no puede coincidir en la mitad de la lista. Necesitas construir la nueva lista al revés (obviamente :)) que se puede hacer tomando el encabezado y añadiéndolo al reverso del resto de la lista.

+2

Solo quiero señalar que el tercer patrón,' (x: xs: l) 'en realidad puede coincidir, pero no es lo que espera. Coincidirá 'x' con el primer elemento,' xs' con el segundo y 'l' con el resto de la lista. –

1

Prueba este código:

last1 (x:xs:l) = (x,xs,l) 

l no le consigue el último elemento de una lista, se consigue que está el resto de la lista además de las dos primeras variables, que se asignan los dos primeros elementos de una lista.

Cuando escribe una coincidencia de patrón para una lista, a la primera variable se le asigna el primer elemento, y así sucesivamente, hasta que el programa llegue a la última variable, donde se le asigna todo lo que queda. No hay nada especial en agregar un s después de un x, una variable llamada y haría lo mismo.

Si desea obtener el último elemento de una lista, debe crear un patrón similar a (x:xs), y usar recursión en xs y aplicar ese patrón hasta llegar a un elemento de lista, que es el último elemento. Sin embargo, recomendaría leer Adam Bergmark's respuesta para una mejor manera de revertir una lista que no implica encontrar el primer y último elemento de una lista.

0

una versión de trabajo:

swapReverse :: String -> String 
swapReverse (x:xs) = [last xs] ++ swapReverse (init xs) ++ [x] 
swapReverse xs = xs 

Tenga en cuenta que esta aplicación es en cuanto al rendimiento de un desastre. Las implementaciones que usan un pliegue y/o acumuladores son mucho más eficientes.

Cuestiones relacionadas