Try this
map snd $ filter ((== x) . fst) $ zip theList (tail theList)
This won't work on an empty list, you will still need extra code to deal with that.
How does this work?
First, note that the values flow from right to left. The ($) operator allows this to happen. So, the first part evaluated is the zip function.
zip theList (tail theList)
For your example above, this would yield
zip [1,2,3,1,5] [2,3,1,5]
equaling
[(1,2), (2, 3), (3, 1), (1,5)]
which is the set of concurrent pairs in the list.
Next, the filter is applied
filter ((== x) . fst) $ ....
In English, what this says is, filter out only the concurrent pairs whose first element equals x. The output is
[(1,2), (1,5)]
Now we have the list of concurrent pairs starting with 1.
Finally, we apply the map
map snd $ ....
This just pulls out the second value of the pair.
map snd [(1,2), (1,5)] = [2,5]
which is the desired value.
Note, my comment above about failing on the empty list.
This is because tail crashes on the empty list
tail [] --error
There are ways to patch this behavior (see the safe package, for instance), but it is mostly bookkeeping at this point, so I left that for you to work out.
Also note that since all of the functions we used are lazy, this approach would work for lists of infinite length as well.
foo a xs = [y | (x:y:_) <- tails xs, x==a].tailsis from Data.List.