On Sat, Jan 17, 2009 at 7:49 PM, Jeff Wheeler <jeff@nokrev.com> wrote:
On Sat, 2009-01-17 at 17:41 -0500, David Menendez wrote:
That's correct, but I think you'd be better off defining OpApplicative (or Backward, as I call it) locally and avoiding the two reverses.
I'll have to look into this more; I don't really understand applicatives right now, so I can't use them yet. :)
newtype Backwards f a = B { unB :: f a } instance Functor f => Functor (Backwards f) where fmap f = B . fmap f . unB instance Applicative f => Applicative (Backwards f) where pure = B . pure f <*> x = B (unB f <**> unB x) traverseBackwards :: (Traversable t, Applicative f) = (a -> f b) -> t a -> t (f b) traverseBackwards f = unB . traverse (B . f)
If you look at a zipper as a list with a selected element, then it doesn't make sense to talk about a zipper of an empty list.
Apparently a zipper can be empty, as the focus is the rest of the list, not the current element. It seems that my file is not a Zipper, but rather a PointedList (thanks to roconner in #haskell).
This may be terminological confusion. I would have said that a PointedList *is* a zipper. Certainly, from the standpoint that zippers are comonads, you can't have an empty zipper, because you always need to be able to retrieve the selected value.
That being said, I'd prefer fromList to have the type [a] -> Maybe (Zipper a), and similarly with next and previous. If people want to live dangerously, they can use fromJust.
I agree, and I've made this change. I found this annoying on next/previous though, so I've created a tryNext/tryPrevious that'll return an unchanged PointedList if it's already on the end.
I would define tryNext in terms of next, rather than the other way around, but I guess it shouldn't make much difference. I'm also not sure that returning the original pointed list is a good idea, since trying to move beyond the boundaries of the zipper will usually be an error. -- Dave Menendez <dave@zednenem.com> <http://www.eyrie.org/~zednenem/>