From anthony_clayden at clear.net.nz Wed Mar 10 00:02:04 2021
From: anthony_clayden at clear.net.nz (Anthony Clayden)
Date: Wed, 10 Mar 2021 13:02:04 +1300
Subject: Pattern synonym 'Required' constraints === Datatype Contexts(?)
Message-ID:
I must be slow on the uptake. I've just grokked this equivalence -- or is
it? Consider
> data Eq a => Set a = NilSet | ConsSet a (Set a) -- from the
Language report
>
> -- ConsSet :: forall a. Eq a => a -> Set a => Set a -- inferred/per
report
>
> -- equiv with Pattern syn 'Required' constraint
> data Set' a = NilSet' | ConsSet' a (Set' a) -- no DT context
>
> pattern ConsSetP :: (Eq a) => () => a -> (Set' a) -> (Set' a)
> pattern ConsSetP x xs = ConsSet' x xs
>
> ffP ((ConsSet x xs), (ConsSetP y ys)) = (x, y)
>
> -- ffP :: forall {a} {b}. (Eq a, Eq b) => (Set a, Set' b) -> (a, b)
-- inferred
The signature decl for `ConsSetP` explicitly gives both the Required `(Eq
a) =>` and Provided `() =>` constraints, but the Provided could be omitted,
because it's empty. I get the same signature for both `ConsSetP` as
`ConsSet` with the DT Context. Or is there some subtle difference?
This typing effect is what got DT Contexts called 'stupid theta' and
deprecated/removed from the language standard. ("widely considered a
mis-feature", as GHC is keen to tell me.) If there's no difference, why
re-introduce the feature for Patterns? That is, why go to the bother of the
double-context business, which looks weird, and behaves counter to usual
signatures:
> foo :: (Eq a) => (Show a) => a -> a
> -- foo :: forall {a}. (Eq a, Show a) => a -> a -- inferred
There is a slight difference possible with Pattern synonyms, compare:
> pattern NilSetP :: (Eq a) => () => (Set' a)
> pattern NilSetP = NilSet'
>
> -- NilSetP :: forall {a}. Eq a => Set' a -- inferred
> -- NilSet :: forall {a}. => Set a --
inferred/per report
Using `NilSetP` somewhere needs giving an explicit signature/otherwise your
types are ambiguous; but arguably that's a better discipline than using
`NilSet` and allowing a Set with non-comparable element types.
AntC
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
From rae at richarde.dev Thu Mar 11 15:08:26 2021
From: rae at richarde.dev (Richard Eisenberg)
Date: Thu, 11 Mar 2021 15:08:26 +0000
Subject: Pattern synonym 'Required' constraints === Datatype Contexts(?)
In-Reply-To:
References:
Message-ID: <010f017821d4f08d-185a3d00-7e63-4b4c-a420-b649eed599bc-000000@us-east-2.amazonses.com>
You're right that these features sit in a similar space. The difference is that, with a pattern synonym, the required context might be useful. This is because pattern synonyms can perform computation (via view patterns), and this computation might plausibly require some class constraint. An easy example:
> pattern Positive :: (Ord a, Num a) => a
> pattern Positive <- ((>0) -> True)
Here, the required context is helpful. On the other hand, because matching against a data constructor never does computation, the constraints are never useful in this way.
Richard
> On Mar 9, 2021, at 7:02 PM, Anthony Clayden wrote:
>
> I must be slow on the uptake. I've just grokked this equivalence -- or is it? Consider
>
> > data Eq a => Set a = NilSet | ConsSet a (Set a) -- from the Language report
> >
> > -- ConsSet :: forall a. Eq a => a -> Set a => Set a -- inferred/per report
> >
> > -- equiv with Pattern syn 'Required' constraint
> > data Set' a = NilSet' | ConsSet' a (Set' a) -- no DT context
> >
> > pattern ConsSetP :: (Eq a) => () => a -> (Set' a) -> (Set' a)
> > pattern ConsSetP x xs = ConsSet' x xs
> >
> > ffP ((ConsSet x xs), (ConsSetP y ys)) = (x, y)
> >
> > -- ffP :: forall {a} {b}. (Eq a, Eq b) => (Set a, Set' b) -> (a, b) -- inferred
>
> The signature decl for `ConsSetP` explicitly gives both the Required `(Eq a) =>` and Provided `() =>` constraints, but the Provided could be omitted, because it's empty. I get the same signature for both `ConsSetP` as `ConsSet` with the DT Context. Or is there some subtle difference?
>
> This typing effect is what got DT Contexts called 'stupid theta' and deprecated/removed from the language standard. ("widely considered a mis-feature", as GHC is keen to tell me.) If there's no difference, why re-introduce the feature for Patterns? That is, why go to the bother of the double-context business, which looks weird, and behaves counter to usual signatures:
>
> > foo :: (Eq a) => (Show a) => a -> a
> > -- foo :: forall {a}. (Eq a, Show a) => a -> a -- inferred
>
> There is a slight difference possible with Pattern synonyms, compare:
>
> > pattern NilSetP :: (Eq a) => () => (Set' a)
> > pattern NilSetP = NilSet'
> >
> > -- NilSetP :: forall {a}. Eq a => Set' a -- inferred
> > -- NilSet :: forall {a}. => Set a -- inferred/per report
>
> Using `NilSetP` somewhere needs giving an explicit signature/otherwise your types are ambiguous; but arguably that's a better discipline than using `NilSet` and allowing a Set with non-comparable element types.
>
> AntC
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
From lennart at augustsson.net Thu Mar 11 18:27:53 2021
From: lennart at augustsson.net (Lennart Augustsson)
Date: Thu, 11 Mar 2021 10:27:53 -0800
Subject: Pattern synonym 'Required' constraints === Datatype Contexts(?)
In-Reply-To: <010f017821d4f08d-185a3d00-7e63-4b4c-a420-b649eed599bc-000000@us-east-2.amazonses.com>
References:
<010f017821d4f08d-185a3d00-7e63-4b4c-a420-b649eed599bc-000000@us-east-2.amazonses.com>
Message-ID:
The required context on pattern synonyms isn't just useful, it's
necessary. Since arbitrary computation can happen in both the pattern
matching and construction we need the context.
Take Richard's example, without the context on Positive we would infer the
wrong type for any use of the Positive synonym.
On Thu, Mar 11, 2021 at 7:09 AM Richard Eisenberg wrote:
> You're right that these features sit in a similar space. The difference is
> that, with a pattern synonym, the required context might be useful. This is
> because pattern synonyms can perform computation (via view patterns), and
> this computation might plausibly require some class constraint. An easy
> example:
>
> pattern Positive :: (Ord a, Num a) => a
> pattern Positive <- ((>0) -> True)
>
>
> Here, the required context is helpful. On the other hand, because matching
> against a data constructor never does computation, the constraints are
> never useful in this way.
>
> Richard
>
> On Mar 9, 2021, at 7:02 PM, Anthony Clayden
> wrote:
>
> I must be slow on the uptake. I've just grokked this equivalence -- or is
> it? Consider
>
> > data Eq a => Set a = NilSet | ConsSet a (Set a) -- from the
> Language report
> >
> > -- ConsSet :: forall a. Eq a => a -> Set a => Set a -- inferred/per
> report
> >
> > -- equiv with Pattern syn 'Required' constraint
> > data Set' a = NilSet' | ConsSet' a (Set' a) -- no DT context
> >
> > pattern ConsSetP :: (Eq a) => () => a -> (Set' a) -> (Set' a)
> > pattern ConsSetP x xs = ConsSet' x xs
> >
> > ffP ((ConsSet x xs), (ConsSetP y ys)) = (x, y)
> >
> > -- ffP :: forall {a} {b}. (Eq a, Eq b) => (Set a, Set' b) -> (a, b)
> -- inferred
>
> The signature decl for `ConsSetP` explicitly gives both the Required `(Eq
> a) =>` and Provided `() =>` constraints, but the Provided could be omitted,
> because it's empty. I get the same signature for both `ConsSetP` as
> `ConsSet` with the DT Context. Or is there some subtle difference?
>
> This typing effect is what got DT Contexts called 'stupid theta' and
> deprecated/removed from the language standard. ("widely considered a
> mis-feature", as GHC is keen to tell me.) If there's no difference, why
> re-introduce the feature for Patterns? That is, why go to the bother of the
> double-context business, which looks weird, and behaves counter to usual
> signatures:
>
> > foo :: (Eq a) => (Show a) => a -> a
> > -- foo :: forall {a}. (Eq a, Show a) => a -> a -- inferred
>
> There is a slight difference possible with Pattern synonyms, compare:
>
> > pattern NilSetP :: (Eq a) => () => (Set' a)
> > pattern NilSetP = NilSet'
> >
> > -- NilSetP :: forall {a}. Eq a => Set' a -- inferred
> > -- NilSet :: forall {a}. => Set a --
> inferred/per report
>
> Using `NilSetP` somewhere needs giving an explicit signature/otherwise
> your types are ambiguous; but arguably that's a better discipline than
> using `NilSet` and allowing a Set with non-comparable element types.
>
> AntC
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
From gergo at erdi.hu Fri Mar 12 10:03:48 2021
From: gergo at erdi.hu (=?ISO-8859-2?Q?=C9RDI_Gerg=F5?=)
Date: Fri, 12 Mar 2021 18:03:48 +0800 (+08)
Subject: Pattern synonym 'Required' constraints === Datatype
Contexts(?)
In-Reply-To: <010f017821d4f08d-185a3d00-7e63-4b4c-a420-b649eed599bc-000000@us-east-2.amazonses.com>
References:
<010f017821d4f08d-185a3d00-7e63-4b4c-a420-b649eed599bc-000000@us-east-2.amazonses.com>
Message-ID:
On Thu, 11 Mar 2021, Richard Eisenberg wrote:
> You're right that these features sit in a similar space. The difference is that, with
> a pattern synonym, the required context might be useful. This is because pattern
> synonyms can perform computation (via view patterns), and this computation might
> plausibly require some class constraint. An easy example:
> pattern Positive :: (Ord a, Num a) => a
> pattern Positive <- ((>0) -> True)
Heck, even just pattern matching on `0` (no view patterns) Requires the
scrutinee to be both `Num` and `Eq`. To see why, ponder the inferred
type of the following function:
```
foo 0 = True
foo _ = False
```
From anthony_clayden at clear.net.nz Fri Mar 12 11:37:57 2021
From: anthony_clayden at clear.net.nz (Anthony Clayden)
Date: Sat, 13 Mar 2021 00:37:57 +1300
Subject: Pattern synonym 'Required' constraints === Datatype Contexts(?)
Message-ID:
Thank you Richard, Lennart, *GergÅ‘*
>* pattern Positive :: (Ord a, Num a) => a*
>* pattern Positive <- ((>0) -> True)*
*Heh heh, there's another surprise/undocumented 'feature'.*
*It's not necessary to give a signature for pattern `Positive`, GHC
will infer that from the decl.*
*I was surprised to see `True`, and even more surprised there wasn't a
`Bool` in the signature. I guess that's so `Positive` can appear as a
pattern in a case expr. To dig out the positive value in a lambda
expr, it seems I go*
*> (\p at Positive -> p) 5 -- returns 5*
*Seems I can't use any trick like that to turn `Positive` into
explicitly bidirectional. I also tried*
>* pattern Positive' <- ((>0) -> ())*
*But that's rejected '"** Couldn't match expected type `Bool' with
actual type `()'".
Is the hidden `Bool` documented somewhere? (Doesn't seem to be in the
User Guide nor the wiki nor the paper, on a quick scan.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
From rae at richarde.dev Fri Mar 12 18:30:49 2021
From: rae at richarde.dev (Richard Eisenberg)
Date: Fri, 12 Mar 2021 18:30:49 +0000
Subject: Pattern synonym 'Required' constraints === Datatype Contexts(?)
In-Reply-To:
References:
Message-ID: <010f017827b4970d-c969ad6a-88d8-4f5b-abb0-2399be82d86e-000000@us-east-2.amazonses.com>
No hidden Bool here -- this is just a consequence of the way that view patterns work, where you have to match against the result of the function, in this case, (>0). See https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/view_patterns.html
Richard
> On Mar 12, 2021, at 6:37 AM, Anthony Clayden wrote:
>
> Thank you Richard, Lennart, GergÅ‘
>
> > pattern Positive :: (Ord a, Num a) => a
> > pattern Positive <- ((>0) -> True)
>
> Heh heh, there's another surprise/undocumented 'feature'.
> It's not necessary to give a signature for pattern `Positive`, GHC will infer that from the decl.
> I was surprised to see `True`, and even more surprised there wasn't a `Bool` in the signature. I guess that's so `Positive` can appear as a pattern in a case expr. To dig out the positive value in a lambda expr, it seems I go
>
> > (\p at Positive -> p) 5 -- returns 5
>
> Seems I can't use any trick like that to turn `Positive` into explicitly bidirectional. I also tried
>
> > pattern Positive' <- ((>0) -> ())
>
> But that's rejected '"* Couldn't match expected type `Bool' with actual type `()'".
> Is the hidden `Bool` documented somewhere? (Doesn't seem to be in the User Guide nor the wiki nor the paper, on a quick scan.)
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: