Pattern Synonym Signature Confusion

I think that the current state of pattern synonym signatures is quite confusing, especially regarding the constraints. For those unfamiliar, a signature looks like the following, pattern ExNumPat :: (Show b) => (Num a, Eq a) => b -> T a The first constraint being the "provided constraints" and the second the "required constraints". My main concern is when only a single constraint is specified then these are treated as the provided constraints. The manual gives the reason that this is the "more common" choice. It seems that this motivation is driven by the original ticket which had a lengthy discussion about GADTs. In my experience, the opposite is true, it is more common to have required constraints. This is true especially in a few common cases such as "pattern Foo = 27", where users define pattern synonyms which have (overloaded) literals on the RHS. The most general signature for such a pattern is "pattern :: () => (Eq a, Num a) => a". For this reason, I think it would be better if either 1. Only specifying one constraint corresponded to the required constraints 2. We required users to specify both sets of constraints, even if the provided constraints are empty. In terms of breakage, I don't think that pattern synonym signatures are widely used yet. In both schemes it is possible to write backwards compatible code by writing both sets of constraints. I think a lot of the confusion also arises from the unusual form of the signature, it is unusual to specify two sets of constraints and I suspect users tends to assume that a single set of constraints is either provided or required depending on what they want it to mean. Forcing the specification of both, forces the user to make the distinction earlier rather than trying to decipher error messages. Thoughts? Matt

2015-10-01 13:23 GMT+02:00 Matthew Pickering
I think that the current state of pattern synonym signatures is quite confusing, especially regarding the constraints. [...]
Thanks to an off-list email from Matthew (thanks for that!) I found out that pattern FOO = 1234 :: Int behaves differently from pattern FOO :: Int pattern FOO = 1234 In the former case one has to use ScopedTypeVariables, in the latter case it works without it. This is not really intuitive, although I'll have to admit that I've had only a cursory look at the "Typing of pattern synonyms" section in the GHC manual. But even after re-reading it, it's not really clear where the difference in the above example comes from. So in a nutshell: +1 for the "quite confusing" argument. Cheers, S.

On 01/10/2015 18:12, Sven Panne wrote:
2015-10-01 13:23 GMT+02:00 Matthew Pickering
mailto:matthewtpickering@gmail.com>: I think that the current state of pattern synonym signatures is quite confusing, especially regarding the constraints. [...]
Thanks to an off-list email from Matthew (thanks for that!) I found out that
pattern FOO = 1234 :: Int
behaves differently from
pattern FOO :: Int pattern FOO = 1234
In the former case one has to use ScopedTypeVariables, in the latter case it works without it. This is not really intuitive, although I'll have to admit that I've had only a cursory look at the "Typing of pattern synonyms" section in the GHC manual. But even after re-reading it, it's not really clear where the difference in the above example comes from.
So in a nutshell: +1 for the "quite confusing" argument.
Isn't that consistent with patterns in general, where something like f (5 :: Int) = 6 is only legal with ScopedTypeVariables on? Cheers, Ganesh

Matthew What you say sounds reasonable to me. I certainly don't have a strong opinion that the current design is the "right" one. Simon | -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Matthew | Pickering | Sent: 01 October 2015 12:23 | To: GHC developers | Subject: Pattern Synonym Signature Confusion | | I think that the current state of pattern synonym signatures is quite | confusing, especially regarding the constraints. For those unfamiliar, | a signature looks like the following, | | pattern ExNumPat :: (Show b) => (Num a, Eq a) => b -> T a | | The first constraint being the "provided constraints" and the second | the "required constraints". | | My main concern is when only a single constraint is specified then | these are treated as the provided constraints. The manual gives the | reason that this is the "more common" choice. It seems that this | motivation is driven by the original ticket which had a lengthy | discussion about GADTs. In my experience, the opposite is true, it is | more common to have required constraints. | | This is true especially in a few common cases such as "pattern Foo = | 27", where users define pattern synonyms which have (overloaded) | literals on the RHS. The most general signature for such a pattern is | "pattern :: () => (Eq a, Num a) => a". | | For this reason, I think it would be better if either | | 1. Only specifying one constraint corresponded to the required constraints | 2. We required users to specify both sets of constraints, even if the | provided constraints are empty. | | In terms of breakage, I don't think that pattern synonym signatures | are widely used yet. In both schemes it is possible to write backwards | compatible code by writing both sets of constraints. | | I think a lot of the confusion also arises from the unusual form of | the signature, it is unusual to specify two sets of constraints and I | suspect users tends to assume that a single set of constraints is | either provided or required depending on what they want it to mean. | Forcing the specification of both, forces the user to make the | distinction earlier rather than trying to decipher error messages. | | Thoughts? | | Matt | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haske | ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc- | devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c403e493d2a54438d264 | 408d2ca52b5b9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=sjc2n0Gm1A%2ffe | OKEpntmEYqTfbYaLvk2sb%2b2vUqIqLU%3d

I have grepped the whole of hackage. There are only 10 pattern synonym
signatures in total in three separate packages (one of them being my
own). None of them specify provided constraints, three of them specify
required constraints. Of course this is a very small sample size but
it means that there wouldn't be any widespread breakage either way
with this proposal.
```
../hackage-packages//ghc-exactprint-0.4.1.0/tests/examples/Sigs.hs:pattern
Single :: () => (Show a) => a -> [a]
../hackage-packages//structs-0/src/Data/Struct/Internal.hs:pattern
Struct :: () => Struct t => SmallMutableArray# s Any -> t s
../hackage-packages//structs-0/src/Data/Struct/Internal.hs:pattern Nil
:: forall t s. () => Struct t => t s
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
Ref' :: Path phi ix top -> HWithRef phi top ix
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
Const' :: forall top. Integer -> HWithRef AST top AExpr
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
BConst' :: forall top. Bool -> HWithRef AST top BExpr
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
And' :: forall top. HWithRef AST top BExpr -> HWithRef AST top BExpr
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
GT' :: forall top. HWithRef AST top AExpr -> HWithRef AST top AExpr
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
GT_0 :: Path AST top AExpr -> Path AST top BExpr
../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern
Neg_0 :: Path AST top AExpr -> Path AST top AExpr
```
On Thu, Oct 1, 2015 at 10:48 PM, Simon Peyton Jones
Matthew
What you say sounds reasonable to me. I certainly don't have a strong opinion that the current design is the "right" one.
Simon
| -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Matthew | Pickering | Sent: 01 October 2015 12:23 | To: GHC developers | Subject: Pattern Synonym Signature Confusion | | I think that the current state of pattern synonym signatures is quite | confusing, especially regarding the constraints. For those unfamiliar, | a signature looks like the following, | | pattern ExNumPat :: (Show b) => (Num a, Eq a) => b -> T a | | The first constraint being the "provided constraints" and the second | the "required constraints". | | My main concern is when only a single constraint is specified then | these are treated as the provided constraints. The manual gives the | reason that this is the "more common" choice. It seems that this | motivation is driven by the original ticket which had a lengthy | discussion about GADTs. In my experience, the opposite is true, it is | more common to have required constraints. | | This is true especially in a few common cases such as "pattern Foo = | 27", where users define pattern synonyms which have (overloaded) | literals on the RHS. The most general signature for such a pattern is | "pattern :: () => (Eq a, Num a) => a". | | For this reason, I think it would be better if either | | 1. Only specifying one constraint corresponded to the required constraints | 2. We required users to specify both sets of constraints, even if the | provided constraints are empty. | | In terms of breakage, I don't think that pattern synonym signatures | are widely used yet. In both schemes it is possible to write backwards | compatible code by writing both sets of constraints. | | I think a lot of the confusion also arises from the unusual form of | the signature, it is unusual to specify two sets of constraints and I | suspect users tends to assume that a single set of constraints is | either provided or required depending on what they want it to mean. | Forcing the specification of both, forces the user to make the | distinction earlier rather than trying to decipher error messages. | | Thoughts? | | Matt | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haske | ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc- | devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c403e493d2a54438d264 | 408d2ca52b5b9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=sjc2n0Gm1A%2ffe | OKEpntmEYqTfbYaLvk2sb%2b2vUqIqLU%3d

Hi.
Matthew, I'm in favour of your proposed change (probably slightly in
favour of option 2 compared to option 1). I must say that the whole
"double constraint" syntax is very confusing no matter what. If we
could somehow find a better / more explicit way to specify provided
constraints, that would be even better.
Cheers,
Andres
On Fri, Oct 2, 2015 at 1:58 PM, Matthew Pickering
I have grepped the whole of hackage. There are only 10 pattern synonym signatures in total in three separate packages (one of them being my own). None of them specify provided constraints, three of them specify required constraints. Of course this is a very small sample size but it means that there wouldn't be any widespread breakage either way with this proposal.
``` ../hackage-packages//ghc-exactprint-0.4.1.0/tests/examples/Sigs.hs:pattern Single :: () => (Show a) => a -> [a] ../hackage-packages//structs-0/src/Data/Struct/Internal.hs:pattern Struct :: () => Struct t => SmallMutableArray# s Any -> t s ../hackage-packages//structs-0/src/Data/Struct/Internal.hs:pattern Nil :: forall t s. () => Struct t => t s ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern Ref' :: Path phi ix top -> HWithRef phi top ix ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern Const' :: forall top. Integer -> HWithRef AST top AExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern BConst' :: forall top. Bool -> HWithRef AST top BExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern And' :: forall top. HWithRef AST top BExpr -> HWithRef AST top BExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern GT' :: forall top. HWithRef AST top AExpr -> HWithRef AST top AExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern GT_0 :: Path AST top AExpr -> Path AST top BExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern Neg_0 :: Path AST top AExpr -> Path AST top AExpr ```
On Thu, Oct 1, 2015 at 10:48 PM, Simon Peyton Jones
wrote: Matthew
What you say sounds reasonable to me. I certainly don't have a strong opinion that the current design is the "right" one.
Simon
| -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Matthew | Pickering | Sent: 01 October 2015 12:23 | To: GHC developers | Subject: Pattern Synonym Signature Confusion | | I think that the current state of pattern synonym signatures is quite | confusing, especially regarding the constraints. For those unfamiliar, | a signature looks like the following, | | pattern ExNumPat :: (Show b) => (Num a, Eq a) => b -> T a | | The first constraint being the "provided constraints" and the second | the "required constraints". | | My main concern is when only a single constraint is specified then | these are treated as the provided constraints. The manual gives the | reason that this is the "more common" choice. It seems that this | motivation is driven by the original ticket which had a lengthy | discussion about GADTs. In my experience, the opposite is true, it is | more common to have required constraints. | | This is true especially in a few common cases such as "pattern Foo = | 27", where users define pattern synonyms which have (overloaded) | literals on the RHS. The most general signature for such a pattern is | "pattern :: () => (Eq a, Num a) => a". | | For this reason, I think it would be better if either | | 1. Only specifying one constraint corresponded to the required constraints | 2. We required users to specify both sets of constraints, even if the | provided constraints are empty. | | In terms of breakage, I don't think that pattern synonym signatures | are widely used yet. In both schemes it is possible to write backwards | compatible code by writing both sets of constraints. | | I think a lot of the confusion also arises from the unusual form of | the signature, it is unusual to specify two sets of constraints and I | suspect users tends to assume that a single set of constraints is | either provided or required depending on what they want it to mean. | Forcing the specification of both, forces the user to make the | distinction earlier rather than trying to decipher error messages. | | Thoughts? | | Matt | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haske | ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc- | devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c403e493d2a54438d264 | 408d2ca52b5b9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=sjc2n0Gm1A%2ffe | OKEpntmEYqTfbYaLvk2sb%2b2vUqIqLU%3d
ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

I made a ticket[1] to track the progress of this issue. I agree that
the whole situation is confusing but I can't see anything much better.
[1]: https://ghc.haskell.org/trac/ghc/ticket/10928#ticket
On Sat, Oct 3, 2015 at 11:04 AM, Andres Loeh
Hi.
Matthew, I'm in favour of your proposed change (probably slightly in favour of option 2 compared to option 1). I must say that the whole "double constraint" syntax is very confusing no matter what. If we could somehow find a better / more explicit way to specify provided constraints, that would be even better.
Cheers, Andres
On Fri, Oct 2, 2015 at 1:58 PM, Matthew Pickering
wrote: I have grepped the whole of hackage. There are only 10 pattern synonym signatures in total in three separate packages (one of them being my own). None of them specify provided constraints, three of them specify required constraints. Of course this is a very small sample size but it means that there wouldn't be any widespread breakage either way with this proposal.
``` ../hackage-packages//ghc-exactprint-0.4.1.0/tests/examples/Sigs.hs:pattern Single :: () => (Show a) => a -> [a] ../hackage-packages//structs-0/src/Data/Struct/Internal.hs:pattern Struct :: () => Struct t => SmallMutableArray# s Any -> t s ../hackage-packages//structs-0/src/Data/Struct/Internal.hs:pattern Nil :: forall t s. () => Struct t => t s ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern Ref' :: Path phi ix top -> HWithRef phi top ix ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern Const' :: forall top. Integer -> HWithRef AST top AExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern BConst' :: forall top. Bool -> HWithRef AST top BExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern And' :: forall top. HWithRef AST top BExpr -> HWithRef AST top BExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern GT' :: forall top. HWithRef AST top AExpr -> HWithRef AST top AExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern GT_0 :: Path AST top AExpr -> Path AST top BExpr ../hackage-packages//transformations-0.2.0.0/examples/MultiRec.hs:pattern Neg_0 :: Path AST top AExpr -> Path AST top AExpr ```
On Thu, Oct 1, 2015 at 10:48 PM, Simon Peyton Jones
wrote: Matthew
What you say sounds reasonable to me. I certainly don't have a strong opinion that the current design is the "right" one.
Simon
| -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Matthew | Pickering | Sent: 01 October 2015 12:23 | To: GHC developers | Subject: Pattern Synonym Signature Confusion | | I think that the current state of pattern synonym signatures is quite | confusing, especially regarding the constraints. For those unfamiliar, | a signature looks like the following, | | pattern ExNumPat :: (Show b) => (Num a, Eq a) => b -> T a | | The first constraint being the "provided constraints" and the second | the "required constraints". | | My main concern is when only a single constraint is specified then | these are treated as the provided constraints. The manual gives the | reason that this is the "more common" choice. It seems that this | motivation is driven by the original ticket which had a lengthy | discussion about GADTs. In my experience, the opposite is true, it is | more common to have required constraints. | | This is true especially in a few common cases such as "pattern Foo = | 27", where users define pattern synonyms which have (overloaded) | literals on the RHS. The most general signature for such a pattern is | "pattern :: () => (Eq a, Num a) => a". | | For this reason, I think it would be better if either | | 1. Only specifying one constraint corresponded to the required constraints | 2. We required users to specify both sets of constraints, even if the | provided constraints are empty. | | In terms of breakage, I don't think that pattern synonym signatures | are widely used yet. In both schemes it is possible to write backwards | compatible code by writing both sets of constraints. | | I think a lot of the confusion also arises from the unusual form of | the signature, it is unusual to specify two sets of constraints and I | suspect users tends to assume that a single set of constraints is | either provided or required depending on what they want it to mean. | Forcing the specification of both, forces the user to make the | distinction earlier rather than trying to decipher error messages. | | Thoughts? | | Matt | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haske | ll.org%2fcgi-bin%2fmailman%2flistinfo%2fghc- | devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c403e493d2a54438d264 | 408d2ca52b5b9%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=sjc2n0Gm1A%2ffe | OKEpntmEYqTfbYaLvk2sb%2b2vUqIqLU%3d
ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
participants (5)
-
Andres Loeh
-
Ganesh Sittampalam
-
Matthew Pickering
-
Simon Peyton Jones
-
Sven Panne