Re: [Haskell-beginners] Just clarifying the "pred" and "succ" functions in Haskell

So, I may look at doing what I would call "lpred" and lsucc" - the predecessor and successor of a list element. I'm somewhat surprised that (from what I can tell) Haskell doesn't seem to have those two functions for a list. I may be wrong.... Again, lists don't work that way; a list in Haskell is a single immutable object, you can pull items from it using (!!), head, etc., but you can't have a pointer into the "middle" of a list. You can have a sublist (for example, `tail ["foo", "bar", "baz"]' = `["bar", "baz"]') --- but you can't get from there to the "foo", as it isn't
Andy Elvey wrote: part of that new list. (This despite the fact that what `tail' gives you is going to be shared in actual storage with the original list. You don't have a backpointer into that original list to follow.) This is actually a feature of the Haskell model: it's usually easier to reason about these kinds of structures, where you can treat any operation as producing a new object and the Haskell compiler takes care of optimizations for you (shared representations, possibly recognizing that it can quietly do an update-in-place because you can't possibly reach the old value, etc.). You may want to take a look at the Seq type defined in the Data.Seq module, though; you have a `view' (what you can think of as a cursor) on a given Seq which can be moved back and forth. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Sat, Feb 06, 2010 at 01:45:58AM -0500, Brandon S. Allbery KF8NH wrote:
Andy Elvey wrote:
So, I may look at doing what I would call "lpred" and lsucc" - the predecessor and successor of a list element. I'm somewhat surprised that (from what I can tell) Haskell doesn't seem to have those two functions for a list. I may be wrong....
Again, lists don't work that way; a list in Haskell is a single immutable object, you can pull items from it using (!!), head, etc., but you can't have a pointer into the "middle" of a list. You can have a sublist (for example, `tail ["foo", "bar", "baz"]' = `["bar", "baz"]') --- but you can't get from there to the "foo", as it isn't part of that new list. (This despite the fact that what `tail' gives you is going to be shared in actual storage with the original list. You don't have a backpointer into that original list to follow.)
Although we can't have a pointer to the middle of a list [a], we can have another data struture that behaves sort of as if we had that pointer: a zipper. For example, http://hackage.haskell.org/packages/archive/ListZipper/1.1.1.0/doc/html/Data... To understand a list zipper you could think of it as something like struct zipper { list left, right; } So we track our "position" by tracking what's on the left and what's on the right. By using the API of the link above you could have something similar to what you wanted: lpred :: Zipper a -> a lpred = focus . left lsucc :: Zipper a -> a lsucc = focus . right -- Felipe.

Felipe Lessa wrote: (snip )
Although we can't have a pointer to the middle of a list [a], we can have another data struture that behaves sort of as if we had that pointer: a zipper. For example,
http://hackage.haskell.org/packages/archive/ListZipper/1.1.1.0/doc/html/Data...
To understand a list zipper you could think of it as something like
struct zipper { list left, right; }
So we track our "position" by tracking what's on the left and what's on the right. By using the API of the link above you could have something similar to what you wanted:
lpred :: Zipper a -> a lpred = focus . left
lsucc :: Zipper a -> a lsucc = focus . right
-- Felipe.
Hi Felipe - Thanks very much for that! That's very handy to know. I think that I'll base my lpred and lsucc on this approach. Bye for now - - Andy
participants (3)
-
Andy Elvey
-
Brandon S. Allbery KF8NH
-
Felipe Lessa