Andrew McKinlay's solution is the real "true" functional solution for a real skip-list here, but it has a downside. You pay logarithmic time to access an element, but now mutation beyond the head element becomes hopeless. The answer you want is buried down in countless path-copies!
Can we do better?
Part of the problem there is that there are multiple paths from -infinity to your item.
But if you think through the algorithms for searching a skiplist, you never use that fact.
We can think of each node in the tree as having a preferred link, the top-most link to it from the left, which in some sense can be thought of as 'owning' that entry.
Now we can consider the notion of a 'finger' into a data structure, which is a functional technique that enables you to focus on one particular element, and supply a path back to the root.
Now we can start with a simple skip-list
-inf-------------------> 16
-inf ------> 8 --------> 16
-inf -> 4 -> 8 -> 12 --> 16
Expanding it by level:
-inf-------------------> 16
| |
v v
-inf ------> 8 --------> 16
| | |
v v v
-inf -> 4 -> 8 -> 12 --> 16
Strip out all but the preferred pointers:
-inf-------------------> 16
| |
v v
-inf ------> 8 16
| | |
v v v
-inf -> 4 8 -> 12 16
Then you could move a 'finger' to position 8 by tracking all the pointers you'd have to flip to get there.
-inf ------------------> 16
^ |
| v
-inf <------ 8 16
| | |
v v v
-inf -> 4 8 -> 12 16
From there it is possible to delete 8, pushing the finger somewhere else, and you can continue to navigate through the structure with the finger.
Looked at this way, we can see that the privileged paths in a skip list form a spanning tree!
Moving 1 step with the finger is an O(1) operation if you only have privileged pointers in the tree and use "skinny nodes" like this. If you used fat nodes, then finger movement left/right would be potentially more expensive.
All operations remain O(log n) and you can use a randomized skip-list structure or a deterministic one as usual.
That said, when we break the skiplist down into a notion of a preferred path then we get that a skip-list is just a tree with some redundant non-preferred links we don't need for insert/search/delete, such that the length of each of those paths from the upper right is O(log n) either with high probability or guaranteed depending on your update strategy.
Even without the finger you can maintain O(log n) expected time per insert/delete/update in a tree with this form.
Now, the key word in your question that doesn't make sense is "concurrent". A purely functional data structure doesn't have a notion of in-place mutation. You always produce a new thing. In some sense concurrent functional updates are easy. Everybody gets their own answer! They just can't see each others'.