2012-03-21 12 views
8

Così voluto fare una semplice funzione di stringa inversa in HaskellHaskell pattern matching prima sezione, centrale, e ultimo

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 

Così, c'è un modo per definire un modello struttura in haskell che ha first e last elemento e tutti gli elementi nello middle?

+2

Attenzione alla dichiarazione del tipo :) Probabilmente intendevi 'swapReverse :: String -> String', o forse qualcosa di più generale come' swapReverse :: [a] -> [a] '. –

+0

BTW, trovare l'ultimo elemento di una lista collegata è O (N). Non hai quasi mai voglia di farlo. – hugomg

+0

La firma del tipo deve essere 'String -> String', BTW – Landei

risposta

6

No, non è possibile. Perché? Perché le corrispondenze del modello corrispondono ai valori e alle loro sottoparti, ma il "centro" di una lista non è una sottoparte della lista. L'elenco [1, 2, 3, 4] è 1:(2:(3:(4:[]))), in termini di struttura. Quindi vuoi abbinare first a 1 e last a 4, che sono entrambe le sottoparti della lista, e quindi non squalificate. Ma il middle che si desidera sarebbe 2:(3:[]), che non è una sottoparte dell'elenco e, quindi, non può essere una corrispondenza.

Si noti che non è possibile scrivere un modello per abbinare contemporaneamente il primo e l'ultimo elemento di un elenco. Un pattern ha una profondità che viene fissata al momento della compilazione.

5

pattern matching funziona su costruttori, : è l'unico costruttore di lista in modo non è possibile abbinare a metà della lista. È necessario costruire la nuova lista al contrario (ovviamente :)) che può essere fatta prendendo la testa e aggiungendola sul retro del resto della lista.

+2

Voglio solo osservare che il terzo pattern,' (x: xs: l) 'può effettivamente corrispondere, ma non quello che ci si aspetta. Corrisponde a 'x' con il primo elemento,' xs' al secondo e 'l' al resto della lista. –

1

Prova di questo codice:

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

l non ti ottenere l'ultimo elemento in un elenco, buttare 'il resto della lista, oltre le prime due variabili, che sono assegnati i primi due elementi in una lista.

Quando si scrive una corrispondenza di modello per un elenco, alla prima variabile viene assegnato il primo elemento e così via, fino a quando il programma non arriva all'ultima variabile, a cui viene assegnato tutto ciò che è rimasto. Non c'è niente di speciale nell'aggiungere un dopo una , una variabile denominata farebbe la stessa cosa.

Se si desidera ottenere l'ultimo elemento di un elenco, è necessario creare un modello simile a (x:xs) e utilizzare la ricorsione su xs e applicare tale modello finché non si ottiene un elemento di elenco, che è l'ultimo elemento. Tuttavia, consiglierei di leggere la risposta Adam Bergmark's per un modo migliore per invertire un elenco che non comporta la ricerca del primo e dell'ultimo elemento di una lista.

0

una versione funzionante:

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

Si noti che questa implementazione è la prestazione-saggio un disastro. Le implementazioni che utilizzano una piega e/o accumulatori sono molto più efficienti.