Reputation: 2759
So I wanted to do a simple string reverse function in Haskell
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
So is there a way to define a pattern structure in haskell that has first
and last
element, and all the elements in the middle
?
Upvotes: 8
Views: 4312
Reputation: 54584
A working version:
swapReverse :: String -> String
swapReverse (x:xs) = [last xs] ++ swapReverse (init xs) ++ [x]
swapReverse xs = xs
Note that this implementation is performance-wise a disaster. Implementations using a fold and/or accumulators are much more efficient.
Upvotes: 0
Reputation:
Try this code:
last1 (x:xs:l) = (x,xs,l)
l
doesn't get you the last element in a list, it get's you the rest of the list besides the first two variables, which are assigned the first two elements in a list.
When you write a pattern match for a list, the first variable is assigned the first element, and so on, until the program get's to the last variable, where everything that is left is assigned to it. There is nothing special about adding an s
after an x
, a variable named y
would do the same thing.
If you want to get the last element of a list, you need to create a pattern similar to (x:xs)
, and use recursion on xs
and apply that pattern until you get down to one list element, which is the last element. However, I would recommend reading Adam Bergmark's answer for a better way to reverse a list that does not involve finding the first and last elements of a list.
Upvotes: 2
Reputation: 30227
No, you cannot. Why? Because pattern matches match values and their subparts, but the "middle" of a list isn't a subpart of the list. The list [1, 2, 3, 4]
is 1:(2:(3:(4:[])))
, in terms of its structure. So you want to match first
to 1
and last
to 4
, which are both subparts of the list, and thus not disqualified. But the middle
that you want would be 2:(3:[])
, which is not a subpart of the list, and thus, cannot be a match.
Note that we can't write a pattern to match the first and the last elements of a list simultaneously, either. A pattern has a depth that's fixed at compilation time.
Upvotes: 6
Reputation: 7536
Pattern matching works on constructors, : is the only list constructor so you can not match on the middle of the list. You need to construct the new list backwards (obviously :) ) which can be done by taking the head and appending that to the reverse of the rest of the list.
Upvotes: 5