2

I was seeing what I could do with ImpredicativeTypes and wanted to see what exactly I could do with them. When I ran to what I feel is some strange behavior when it comes to their interaction with TypeClasses.

:t mempty
mempty :: forall a. Monoid a => a

:t Right
Right :: forall a b. b -> Either a b

So I figured I could combine them to make an impredicatively typed expression:

:t Right mempty
Right mempty :: forall a b. Monoid b => Either a b

Looks like the extension does not infer impredicative types, which doesn't seem all that unreasonable, as I know that type inference is not always possible in the general case when you start adding features like this.

So I decided that I would just make the fact that I wanted an impredicative type explicit:

:t Right mempty :: forall a. Either a (forall b. Monoid b => b)

Which to me seemed very reasonable, as I am literally just pasting over the b in the Right type signature with the type of mempty, and then not lifting the forall.

But it give me the following error:

No instance for (Monoid (forall b. Monoid b => b))

Which seems rather absurd. Since every Monoid is an instance of Monoid by definition.

Can someone explain to me what exactly is going on here? Is the issue that it would be too difficult or impossible to actually decide on one instance when actually using the type, and thus GHC really means "No unambiguous / decidable instance for..." rather than "No instance..."?

As a side note when you take typeclasses out of the situation everything appears to work ok:

:t Right undefined :: forall a. Either a (forall b. b)

Type checks and gives me back the impredicative type I specified.

semicolon
  • 2,313
  • 20
  • 30
  • I don't know all the details of what's going on here, but in GHC 8 the behavior changed so that even your original `Right mempty` gives the type you're looking for. See the related https://ghc.haskell.org/trac/ghc/ticket/11319. At any rate, ImpredicativeTypes is unsupported and you shouldn't use it for anything real. – Reid Barton Jul 21 '16 at 20:30
  • 2
    Some of what's going on here is pretty clear, though: GHC needed to make `mempty :: forall b. Monoid b => b`, but `mempty :: Monoid m => m`, so it picked `m = (forall b. Monoid b => b)` and then tried to solve the constraint `Monoid (forall b. Monoid b => b)`, which of course it couldn't (there aren't instances for polytypes). – Reid Barton Jul 21 '16 at 20:33
  • 4
    I'm voting to close this question as off-topic because according to the [GHC documentation](https://downloads.haskell.org/~ghc/8.0.1/docs/html/users_guide/glasgow_exts.html#impredicative-polymorphism), `ImpredicativeTypes` is "extremely flaky", "highly experimental" and "certainly un-supported". It also makes reference to what this feature would do "if it worked". There's simply no point in trying to use this extension unless and until it is fixed. IMHO, the current proposed fix is too invasive. – dfeuer Jul 21 '16 at 20:33
  • @dfeuer I mean I don't think that makes the question off topic, it might make the question not very important, but even if `ImpredicativeTypes` is best avoided I still think it is reasonable for me to be curious what is going on here. – semicolon Jul 21 '16 at 20:36
  • @ReidBarton So is the issue sort of what I was guessing at? That even though for any arbitrary `t` an instance exists, it cannot actually pick one to use in any reasonable way for all possible `t`? – semicolon Jul 21 '16 at 20:38
  • @semicolon, the problem is that basically the only way to answer the question is to trace the execution of the type checker. That doesn't really seem like a reasonable request for a Q & A site. – dfeuer Jul 21 '16 at 20:40
  • @dfeuer Are you positive that is the only meaningful way to answer the question? It seemed like Reid Barton had another (partial?) explanation talking about there not being instances for polytypes. – semicolon Jul 21 '16 at 20:42
  • 2
    Reid was making an informed guess. At present, I don't think *anyone* actually understands the effects of the extension. Most notably, type system hacker extraordinaire Richard Eisenberg has made multiple deep changes to the type system over the past couple years without making any effort to keep the extension up to date with those changes. This is basically because nobody has yet figured out exactly how it should behave, and it's never behaved well enough to make it tractable to even maintain its behavior. – dfeuer Jul 21 '16 at 20:49
  • 1
    Well there definitely aren't any instances for polytypes. The question is about how GHC decides whether to pick `m = b` and then generalize, to get `mempty :: forall b. Monoid b => b`, or to just pick `m = (forall b. Monoid b => b)`. – Reid Barton Jul 21 '16 at 21:04
  • @ReidBarton What reasons are there to pick one of the two options over the other? – semicolon Jul 21 '16 at 21:10
  • 1
    This is not special to `Monoid`, `mempty`, `Right`, or lack of class instance for polytypes - e.g. `(,) 0 :: (forall b. Show b => b) -> (Int, forall b. Show b => b)` just by itself is not well typed. Impredictive types don't work well at all .. the only way I've gotten this to type check is with `(Right \`asTypeOf\` (undefined :: (forall b. Monoid b => b) -> Either () (forall b. Monoid b => b))) mempty`, but I sure can't tell you *why* it works. – user2407038 Jul 21 '16 at 21:21
  • 1
    @user2407038 Well that is enough to convince me the best way to solve this issue is with `:set -XNoImpredicativeTypes`. That honestly makes absolutely zero sense. – semicolon Jul 21 '16 at 21:42

1 Answers1

1

So this question isn't marked as unanswered I guess I will just reiterate what was said in the comments.

Basically ImpredicativeTypes is totally unsupported, and no one really knows how it even should work. So trying to do anything meaningful with it in its current state is a bad idea. So the answer is just: "don't try to do that".

semicolon
  • 2,313
  • 20
  • 30