Reputation: 33
I have recently taken upon myself to learn Haskell and, in one of the first lessons, I have been told to learn how to manipulate lists first. I understand how to pick a list element from it's position like this
myList = [7, 3, 6, 15, 8]
myList !! 3
Now, I would want to know if it's possible to pick a position starting from the last element of the list, just like what I have been doing in Python using this
pythonlist = [7, 3, 6, 15, 8]
pythonlist[-2]
Upvotes: 0
Views: 111
Reputation: 4855
You can do :
(!!<) :: [a] -> Int -> a
l !!< i = (reverse l) !! i
But it means you cannot use negative numbers, only a positive index, but it will look from the end of the list.
Or if you really wanna use negatives:
(!!<) :: [a] -> Int -> a
l !!< i = if i < 0 then l !! (length l + i) else l !! i
Upvotes: 1
Reputation: 21811
In certain cases, yes. You can simply redefine (!!)
to:
xs !! i | i >= 0 = xs Data.List.!! i
| i < 0 = let n = length xs
in xs Data.List.!! (n+i)
However, this isn't really a great idea in Haskell due to laziness. The solution above works on finite lists, which is what you are talking about in Python. Consider what happens on an infinite list, however: [1..] !! (-2)
. We first evaluate length [1..]
, which never terminates! The problem is that you can't index from the end of an infinite list.
Upvotes: 0
Reputation: 120751
First off, if you find yourself accesing lists by index (which you shouldn't often do anyway, it's inefficient and ugly: prefer functional tools such as folds, map
, and the monad instance) then you should better switch to some array data type, e.g. Vector
.
But sure enough it's possible to access lists by index, also from the back:
(!!<) :: [a] -> Int -> a
l !!< i = l !! i'
where i' = length l - i - 1
I hope it's obvious enough how this works. It's even more inefficient than ordinary access because length
traverses the entire list, but there you are.
Upvotes: 1