Opened 23 months ago

Last modified 5 months ago

#11409 new feature request

Cannot instantiate literals using TypeApplications

Reported by: Feuerbach Owned by:
Priority: normal Milestone: 8.4.1
Component: Compiler Version: 8.0.1-rc1
Keywords: TypeApplications Cc: adamgundry, int-index, dfeuer
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: #11352 Differential Rev(s):
Wiki Page:

Description (last modified by Iceland_jack)

Relevant reddit post.


GHCi, version 8.0.1.20160110: http://www.haskell.org/ghc/  :? for help
Prelude> :set -XTypeApplications -fprint-explicit-foralls 
Prelude> :t 42
42 :: forall {a}. Num a => a
Prelude> 42 @Int

<interactive>:3:1: error:
    • Cannot not apply expression of type ‘a0’
      to a visible type argument ‘Int’
    • In the expression: 42 @Int
      In an equation for ‘it’: it = 42 @Int

(Also, "cannot not" looks like a typo.)

Change History (26)

comment:1 Changed 23 months ago by monoidal

This is discussed in the type application paper: https://www.seas.upenn.edu/~sweirich/papers/type-app-extended.pdf, B.4. Overloaded numbers.

comment:2 Changed 23 months ago by rwbarton

Also in ticket:5296#comment:17 and following comments.

comment:3 Changed 23 months ago by simonpj

Keywords: TypeApplications added
Owner: set to goldfire

It'd also be possible to define

integerLit :: Integer -> forall a. Num a => a
integerLit n = fromInteger n

arrange that 3 elaborates to integerLit 3 :: forall a. Num a => a`, and now that will work as expected.

This is so simple to do that it might be worth doing, just to avoid documenting the infelicity. After all, Haskell advertises that 3 :: forall a. Num a => a, so it's annoying if it doesn't behave like that.

comment:4 Changed 23 months ago by adamgundry

Cc: adamgundry added

See also #11352, which is about the same issue for the newfangled overloaded labels (and I guess overloaded string and rational literals should be treated similarly). I experimented with something like Simon's suggestion for overloaded labels, and found that error messages got worse, because it was no longer possible to give a CtOrigin that mentioned the overloaded label as the source. But perhaps there's a way round that?

Alternatively, I suppose we could add a special rule for typechecking a literal applied to a type.

comment:5 in reply to:  4 Changed 23 months ago by simonpj

Replying to adamgundry:

See also #11352, which is about the same issue for the newfangled overloaded labels (and I guess overloaded string and rational literals should be treated similarly).

OK, so that makes it more worth thinking about.

I experimented with something like Simon's suggestion for overloaded labels, and found that error messages got worse, because it was no longer possible to give a CtOrigin that mentioned the overloaded label as the source.

I don't understand why.

  • We continue to have a case in the type checker for integer literals, as now.
  • It elaborates the literal to integerLit 3 with type forall a. Num a => a

When we instantiate that type (which is delayed in the new TypeApplication world) we need a suitable CtOrigin. We get that using exprCtOrigin (see TcExpr.tcApp). It can produce a suitable origin for an integer literal, string -- or field label.

So it seems ok to me. Worth a try?

comment:6 Changed 22 months ago by adamgundry

I think you're right: my problems before arose because I was replacing the overloaded label with the function application in the typechecker, rather than preserving it until the desugarer. Hence exprCtOrigin saw the wrong thing.

On another topic, what about RebindableSyntax? At the moment we have (according to the manual):

An integer literal 368 means "fromInteger (368::Integer)", rather than "Prelude.fromInteger (368::Integer)".

comment:7 Changed 22 months ago by goldfire

I want to note that the Haskell Report says that 3 desugars to fromInteger THREE. Perhaps we can indeed hack around this by using integerLit. But then turning on RebindableSyntax would necessitate using fromInteger, which (due to its membership in the Num class), must have type forall a. Num a => Integer -> a, where the forall a just comes too early. This would mean that 3 @Int would work with -XNoRebindableSyntax but then fail with -XRebindableSyntax (when importing Prelude). It would all be rather unexpected. Worse than the status quo? I don't know.

comment:8 Changed 22 months ago by simonpj

I don't think it'd be too bad if GHC's implementation desugared 3 to integerLit THREE always. For Haskell 98 or 2010, the behaviour would be indistinguishable from the report. But it'd work with TypeApplications too which is a real advantage.

comment:9 Changed 22 months ago by goldfire

What about with RebindableSyntax? Changing that behavior would likely break quite a bit of code.

comment:10 Changed 22 months ago by simonpj

Yurgh. Maybe with RebindableSyntax we stick with fromInteger. Or maybe it's a breaking change.

Maybe we should do nothing until someone really says it's important to them.

comment:11 Changed 22 months ago by Richard Eisenberg <eir@…>

In 80b4c71c/ghc:

Fix typo in error message (#11409)

comment:12 Changed 22 months ago by goldfire

Do please merge the typo fix above. Thanks!

comment:13 Changed 22 months ago by bgamari

Milestone: 8.0.1
Resolution: fixed
Status: newclosed

Cherry-picked to ghc-8.0 as b7af30f79f7e3be105cdd17ee3369a5e483f7f3f.

comment:14 Changed 22 months ago by goldfire

Owner: goldfire deleted
Resolution: fixed
Status: closednew

Thanks for merging the typo fix. But that's nowhere near the nub of this ticket. We might well decide to do nothing, but I'm not convinced we've converged on that solution yet.

comment:15 in reply to:  14 Changed 20 months ago by thoughtpolice

Milestone: 8.0.18.2.1

Replying to goldfire:

Thanks for merging the typo fix. But that's nowhere near the nub of this ticket. We might well decide to do nothing, but I'm not convinced we've converged on that solution yet.

Agreed - in the mean time, let's put this to 8.2.1 since we're probably not going to introduce any large changes for 8.x.

comment:16 Changed 11 months ago by rwbarton

Type: bugfeature request

comment:17 Changed 10 months ago by bgamari

Milestone: 8.2.18.4.1

This won't be happening for 8.2.

comment:18 Changed 8 months ago by Iceland_jack

Description: modified (diff)

comment:19 Changed 8 months ago by int-index

I think the correct way forward here is changing how -XTypeApplications works with partially applied functions. If I can write fromInteger @t n, shouldn't fromInteger n @t behave the same?

comment:20 Changed 8 months ago by int-index

Cc: int-index added

comment:21 Changed 8 months ago by dfeuer

Cc: dfeuer added

comment:22 Changed 8 months ago by rwbarton

f n @t can already be valid and different from f @t n though.

comment:23 Changed 8 months ago by goldfire

The question always is: what type variable is being instantiated? Perhaps f has the type forall a. a -> forall b. b -> (a, b). Then f @t n will be different from f t @n. And, as Stephanie and I describe in our paper, there doesn't seem to be a way to add in extra flexibility.

comment:24 Changed 5 months ago by Iceland_jack

Mentioned in reddit comment

I keep being surprised/disappointed that I can't do 5 @Int and have to do (5 :: Int) instead.

comment:25 Changed 5 months ago by adamgundry

Rather than defining integerLit, perhaps we should just treat a type application to an overloaded literal specially, and say that 5 @Int desugars to fromInteger @Int 5? This would work with RebindableSyntax just fine.

comment:26 in reply to:  25 Changed 5 months ago by Iceland_jack

That sounds good Adam

Note: See TracTickets for help on using tickets.