Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eq & Ord instance for Cursor. #117

Open
kindaro opened this issue Nov 30, 2017 · 2 comments
Open

Eq & Ord instance for Cursor. #117

kindaro opened this issue Nov 30, 2017 · 2 comments

Comments

@kindaro
Copy link

kindaro commented Nov 30, 2017

I observe there are functions in the record for Cursor (precedingSibling' & followingSibling') that prevent me from deriving an Eq or Ord instance and thus, for example, from using Cursor with an ordinary Set, or applying many ordinary list processing functions such as nub. I notice, further, that the only way to construct a Cursor, a function toCursor' found in Text.XML.Cursor.Generic, can accept various functions to put in precedingSibling' & followingSibling', but its only invocation from toCursor specializes both of them to id.

In the light of these observations, could it be possible to simplify the definition of Cursor so as to make a derived Eq instance possible? Or, if not, could you suggest some other way of defining a custom Eq instance that makes sure any further operations on the equal cursors will have equal results? It would be nice if an Ord instance gets to be possible as well.

So far, I had to to toMarkup my cursors and only then compare. This is somewhat uncomfortable. Upon receiving directions, I could attempt to my ability at composing a pull request.

@kindaro
Copy link
Author

kindaro commented Nov 30, 2017

I looked better into the code and yes, we cannot just remove these functions from Cursor because they appear to constitute a major part of the "zipper" algorithm used in the definition of toCursor'. What we can do, and what I actually tried just now, is evaluate a cursor as it comes out of toCursor, and then tediously fix the axes that used to evaluate it themselves. After about a dozen small and trivial modifications, the module compiles and the package passes the tests, with Cursor now featuring derived Eq & Ord instances, as desired.

It can benefit from some cleanup but I am generally ready to submit a pull request. However, if there are programs in the wild that make use of the inner workings of Cursor, they will definitely break.

kindaro added a commit to kindaro/xml that referenced this issue Dec 1, 2017
Adding derived instances of Eq & Ord requires modifying the inner
workings of Cursor record (from the module Text.XML.Cursor.Generic),
specifically:

Siblings in Cursor were represented as functions (type synonym
DiffCursor) that repeatedly append to a (presumably, empty) list until
the desired list of nodes is generated. Such a function would later be
invoked in various public top-level definitions in the module, but upon
an empty list value exclusively.

We rename Cursor to RecursiveCursor and add an eval function that
evaluates a RecursiveCursor to a simpler data structure that takes the
place of Cursor in the module interface. Then, we simplify the
aforementioned public functions, replacing the invocations of DiffCursor
upon an empty list by plain (nullary) values stored in our new, simpler
Cursor data structure.

Thus, we obtain a simpler data structure while preserving the interface.
As the new Cursor data structure is free of functions, an Eq & Ord
instance is now readily derivable.
@snoyberg
Copy link
Owner

snoyberg commented Dec 5, 2017

Due to the knot tying, Cursor is a cyclic data structure. Have you tried using the Eq and Ord instances you've defined? Do they work, or do they loop infinitely?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants