Should (~) be homogeneous or heterogeneous?
Richard Eisenberg
eir at cis.upenn.edu
Fri Nov 27 23:29:45 UTC 2015
On Nov 24, 2015, at 7:54 AM, Simon Peyton Jones <simonpj at microsoft.com> wrote:
> In your example, why do you get KP Any? Why don't you get
>
> class forall k1 k2 kproxy).
> (kproxy :: KProxy k1 ~ 'KP :: KProxy k2) => C kproxy where ...
>
> That may be over-polymorphic, but it'll work ok won't it?
>
All tyvars mentioned in superclass constraints must be introduced in the class head. Your version violates this constraint.
> More generally, why does (2) lead to "trouble"?
Suppose I then say
> instance C ('KP :: KProxy Bool)
GHC needs to prove ('KP :: KProxy Bool) ~ ('KP :: KProxy Any) and it has a hard time doing so.
In any case, I've now seen enough very weird gotchas around heterogeneous ~ to convince me to keep it homogeneous, and to introduce ~~. If you want (~~), you'll need to import it from Data.Type.Equality -- it won't have magical scope like (~) does.
Thanks for the feedback.
Richard
>
> Simon
>
> | -----Original Message-----
> | From: ghc-devs [mailto:ghc-devs-bounces at haskell.org] On Behalf Of
> | Richard Eisenberg
> | Sent: 22 November 2015 19:00
> | To: ghc-devs Devs <ghc-devs at haskell.org>
> | Subject: Should (~) be homogeneous or heterogeneous?
> |
> | Hi devs,
> |
> | I'm desperately working toward getting kind equalities in before the
> | feature freeze. It's coming along nicely. But I have a user-facing
> | issue to work out.
> |
> | * Should (~), as written in user code, require the kinds of its
> | arguments to be equal?
> |
> | Another way of asking the same question is: Should the kind of (~) be
> | 1. forall k. k -> k -> Constraint (HEAD)
> | 2. forall k1 k2. k1 -> k2 -> Constraint (my branch, at the moment)
> |
> | Choice #2 is strictly more powerful and cannot be expressed in terms
> | of #1. But #1 is perhaps more intuitive for programmers, who might
> | expect inference to conclude that the two kinds are the same.
> |
> | Here is an example of where the difference matters:
> |
> | > data KProxy k = KP
> | > class kproxy ~ 'KP => C (kproxy :: KProxy k)
> |
> | We can see that the kind of the type variable kproxy should be (KProxy
> | k). But we still have to infer the kind of the occurrence of 'KP on
> | the left. HEAD sees the kind of kproxy and infers that 'KP should have
> | kind (KProxy k). My branch, on the other hand, doesn't have any reason
> | to constrain the kind of 'KP, and so it gets (KProxy Any), which
> | quickly causes trouble.
> |
> | The fix is easy: add a kind signature.
> |
> | I see two ways forward, corresponding to the choices for the kind of
> | (~) above:
> |
> | 1. Make (~) homogeneous and introduce a new constraint (~~) that is
> | like (~) but heterogeneous. We resign ourselves to explaining the
> | technical, subtle difference between (~) and (~~) into perpetuity.
> |
> | 2. Make (~) heterogeneous. Some people will have to add kind
> | annotations to their code to port from GHC 7.10 to GHC 8.0. But these
> | kind annotations will be fully backward-compatible, and won't require
> | CPP, or warnings, or any other bother. We may have to explain why kind
> | inference around (~) is weaker than it was before.
> |
> |
> | I'm (clearly?) leaning toward #2. But I'd like feedback.
> |
> | Thoughts?
> |
> | Thanks!
> | Richard
> | _______________________________________________
> | ghc-devs mailing list
> | ghc-devs at haskell.org
> | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.h
> | askell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
> | devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c95ca36eba6074ac
> | feefb08d2f36f2700%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=0w0B9q7
> | SJpXzf4UJokFZejYBhiIeASO0bfaJSDVRrJU%3d
>
More information about the ghc-devs
mailing list