Allow separate pattern synonym construction types
Usually today when I go to write a pattern synonym that has non-trivial constraints on construction and pattern matching I wind up having to clutter user facing code with two patterns names and an extra combinator.
I build the bidirectional pattern synonym that contains all the constraints:
pattern JSON :: (FromJSON a, ToJSON a) => () => a -> String pattern JSON a <- (preview _JSON -> Just a) where JSON a = _JSON # a
but because that is so restrictive, I wind up having to supply a unidirectional pattern and combinator for the other two halves of the transformation, lest I require the user to pass me (possibly quite inefficient) dictionaries for unused directions.
pattern JSON' :: ToJSON a => a -> String pattern JSON a <- ... jSON :: FromJSON a => a -> String jSON = ...
I'd really much prefer to be able to split these two sets of constraints up in the explicit bidirectional pattern syntax:
pattern JSON :: ToJSON a => a -> String pattern JSON a <- ... where JSON :: FromJSON a => a -> String JSON a = ...
The outer signature should keep its
Required => Provided => ... context as usual, but the signature of the constructor could be specialized. Now I only have to take one user facing name and the API is much cleaner with no spurious unnecessary constraints being passed. In the absence of such a signature JSON used as a constructor would default to
Required => ... as usual.
Outside of JSON I have examples involving BDD construction, serialization,
Read/Show and pretty much anything where the
From directions are split into separate classes.