ekmett / zippers

Zippers based on lenses and traversals
Other
38 stars 14 forks source link

ipull/pull: move in any direction and pass the result to a continuation #15

Open infinity0 opened 4 years ago

infinity0 commented 4 years ago

As mentioned in the docstring:

This is useful when you need to act on a zipper based on user input, and therefore can't specify what the result zipper type would be. Instead, it is passed to a continuation that can take any (uniform) zipper type. Typically, the continuation could call this same function again, e.g. in a REPL.

Implementing this feature requires dropping the Ord i => data context on Zipper, which is a deprecated GHC extension anyways, so if you don't like this overall feature hopefully we can still merge this fix - it is required, even for me to keep this feature in my own package.

infinity0 commented 4 years ago

huh, weird that GHC gives error about ambiguous types on 8.0.2 - 7.8.4 but is OK with versions both older and newer than that specific range??

infinity0 commented 4 years ago

Implementing this feature requires dropping the Ord i => data context on Zipper,

Never mind, it must have been something to do with an earlier experimental version of the code. It's actually not needed for this current version to work, but nevertheless should be fixed anyway for the sake of modern convention.

infinity0 commented 4 years ago

Another note: this is written in CPS form but could be easily updated to use an existential (which I've done in a local copy elsewhere) if that is preferred:

data SomeUniZipper i a where
  SomeUniZipper :: UniZipper i a h' => !(h' :> a:@i) -> SomeUniZipper i a

When I was coding it from scratch, the CPS version was easier to get working, because the error messages (at least from my perspective) direct you more precisely to what is going wrong and what you need, leading me to write the UniformZipper typeclass.

When you attempt to write this starting off with the existential-GADT as above, the type errors do not make it super-obvious that you need something like UniformZipper, it just talks about ambiguous types inside the GADT. But once you've figured that part out, writing the GADT and making it work is simple.