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

More general type signatures for `makeTraversals` #12

Gabriel439 opened this Issue Jan 11, 2015 · 3 comments


None yet
2 participants
Copy link

Gabriel439 commented Jan 11, 2015

Right now I'm working on a package for exhaustive pattern matching using Traversals (you can find the code here). However, for the trick to work with auto-generated Traversals I need them to have more general types.

For example, let's assume that we were to generate Traversals for the Either type:

data Either a b

makeTraversals ''Either

This would generate something like this:

_Left :: Applicative f => (a -> f a) -> (Either a b -> f (Either a b))
_Left k (Left a) = fmap Left (k a)
_Left _  x       = pure x

_Right :: Applicative f => (b -> f b) -> (Either a b -> f (Either a b))
_Right k (Right a) = fmap Right (k a)
_Right _  x        = pure x

However, I actually need the following more general types, which requires complicating the implementation:

_Left :: Applicative f => (a -> f a') -> (Either a b -> f (Either a' b))
_Left k (Left  a) = fmap Left (k a)
_Left _ (Right b) = pure (Right b)

_Right :: Applicative f => (b -> f b') -> (Either a b -> f (Either a b'))
_Right k (Left  a) = pure (Left a)
_Right k (Right b) = fmap Right (k b)

The type signatures are not the complicated part because they can be omitted (the inferred types would still be correct). What makes this more complex is that you can no longer implement the Traversal in terms of two cases (the matching constructor and the fallback). Instead, you must now provide a case for every constructor.

This is not urgent, because I can work around this by using the makePrisms function from Control.Lens.TH, which does produce the fully general type signatures.


This comment has been minimized.

Copy link

DanBurton commented Feb 28, 2015

I finally put the elbow grease into making this happen. It's still largely untested, but per business-as-usual in Haskell, once it compiled, it seemed to work. You can see for yourself that the traversals generated in examples/traversal-test.lhs are more general now:

$ cabal build
$ ghci examples/traversal-test.lhs
ghci> :t over _B
over _B :: (b -> b') -> Opt b c d -> Opt b' c d
ghci> over _B show (B ())
B "()"

Kindly test this out a little when you can. Meanwhile, I'll review, clean up the code a bit, and maybe even add a test suite. Once I hear back from you ( @Gabriel439 ) I'll release the new version.


This comment has been minimized.

Copy link

Gabriel439 commented Feb 28, 2015

I just gave it a test drive and it works great! I tried it out with my total library and also tried exercising a lot of corner cases and it behaves just the way I expect.


This comment has been minimized.

Copy link

DanBurton commented Mar 1, 2015

Uploaded the new version: Cheers!

@DanBurton DanBurton closed this Mar 1, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.