2012-03-21 14 views
8

Chciałem więc zrobić prostą funkcję ciąg wsteczny w HaskellHaskell wzorzec dopasowania pierwszy, środkowy odcinek, a ostatni

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 

Więc czy jest jakiś sposób, aby zdefiniować strukturę, w Haskell, który ma first i last element i wszystkie elementy w middle?

+2

Uważaj na deklarację typu :) Prawdopodobnie chodziło o 'swapReverse :: String -> String', a może o coś bardziej ogólnego jak' swapReverse :: [a] -> [a] '. –

+0

BTW, znalezienie ostatniego elementu połączonej listy to O (N). Prawie nigdy nie chcesz tego robić. – hugomg

+0

Podpis typu musi być "String -> String', BTW – Landei

Odpowiedz

6

Nie, nie możesz. Czemu? Ponieważ dopasowania wzorca pasują do wartości i ich podelementów, ale "środek" listy nie jest pod-rozdziałem listy. Lista [1, 2, 3, 4] pod względem struktury jest 1:(2:(3:(4:[]))). Więc chcesz dopasować first do 1 i last do 4, które są obu podelementów listy, a zatem nie są dyskwalifikowane. Jednak wymagany jest 2:(3:[]), który nie jest częścią tej listy, a zatem nie może być zgodny.

Pamiętaj, że nie możemy jednocześnie pisać wzorca, który pasowałby do pierwszego i ostatniego elementu listy. Wzór ma głębokość, która jest ustalana w czasie kompilacji.

5

dopasowanie Wzór prace konstruktorów, : jest tylko lista konstruktor więc nie można dopasować na środku listy. Musisz skonstruować nową listę do tyłu (oczywiście :)), co można zrobić, biorąc głowę i dołączając ją na odwrót reszty listy.

+2

Po prostu chcę zauważyć, że trzeci wzorzec,' (x: xs: l) 'może faktycznie pasować, ale nie to, czego się spodziewasz. Dopasuje 'x' z pierwszym elementem,' xs' z drugim i 'l' z resztą listy. –

1

Spróbuj kod:

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

l nie Ci ostatni element na liście, to dostać się wam resztę listy oprócz pierwszych dwóch zmiennych, które są przypisane dwa pierwsze elementy w lista.

Po napisaniu dopasowania wzorca dla listy pierwsza zmienna ma przypisany pierwszy element, itd., Aż program przejdzie do ostatniej zmiennej, do której przypisane jest wszystko, co zostało pozostawione. Nie ma nic szczególnego w dodawaniu s po x, zmienna o nazwie y zrobiłaby to samo.

Jeśli chcesz uzyskać ostatni element listy, musisz utworzyć wzór podobny do (x:xs) i użyć rekursji na xs i zastosować ten wzór, aż dojdziesz do jednego elementu listy, który jest ostatnim elementem. Jednakże, polecam lekturę odpowiedzi Adam Bergmark's dla lepszego sposobu na odwrócenie listy, która nie wymaga znalezienia pierwszego i ostatniego elementu listy.

0

Wersja robocza:

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

Zauważ, że ta implementacja jest wydajność mądry katastrofa. Wdrożenia z wykorzystaniem fałdu i/lub akumulatorów są znacznie bardziej wydajne.

Powiązane problemy