haskell / haskell/error-messages

"Cannot apply expression of type `X` to a visible type argument `Y`" for inferred (braces) type arguments

Open
#542 0 comments 2 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
76
Forks
19
PR merge metrics
No merged PRs in 30d

Description

To reproduce:
```hs
f :: forall {a :: Type}. a -> a
f = Prelude.id

i :: Int
i = f @Int 1
```
GHC complains:
```
• Cannot apply expression of type ‘a0 -> a0’
to a visible type argument ‘Int’
• In the expression: f @Int 1
In an equation for ‘i’: i = f @Int 1
|
52 | i = f @Int 1
| ^^^^^^^^
```

Note that replacing `{a :: Type}` with `(a :: Type)` compiles.

Here the problem is that it is forbidden to apply a type for types inside braces (curly brackets).

Cf https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/type_applications.html#manually-defining-inferred-variables

> Since the 9.0.1 release, GHC permits labelling the user-written type or kind variables as inferred, in contrast to the default of specified. By writing the type variable binder in braces as {tyvar} or {tyvar :: kind}, the new variable will be classified as inferred, not specified. Doing so gives the programmer control over which variables can be manually instantiated and which can’t.

The thing is, it can be easy for users to write curly brackets, in particular because this is often what GHC prints in error messages. This is how I ended up (in a more complex example) using the curly brackets.

I suggest the error message is improved in the following manners:
* mention that the error is related to the `TypeApplications` extension (help discoverability)
* make explicit that the reason why the expression cannot be applied to the type argument is because the type is **explicitly hidden** ("inferred" in the quote above), not specified
* suggest "un-hiding" (i.e. changing from inferred to specified) the type

I am not great at writing error messages, but here is an example that - I think - takes all 3 points above into consideration:
```
• With the TypeApplications language extension,
you cannot apply expression ’f’ of type ‘a0 -> a0’
to a visible type argument ‘Int’
because the type argument ’a0’ is inferred, not specified.
Possible solutions:
• remove the type application ’@Int’
• change the type argument ’a0’ of ’f’ from inferred (wrapped in braces) to specified (wrapped in parentheses)
• In the expression: f @Int 1
In an equation for ‘i’: i = f @Int 1
|
52 | i = f @Int 1
| ^^^^^^^^
```

This issue is a bit related to https://github.com/haskell/error-messages/issues/54 but 54 focuses more on "Explain that type application can only be used when there are type signatures", while here I am focusing on "Explain that type application cannot be used on used on brace-wrapped types".

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the Haskell reproducer in the issue and the linked TypeApplications documentation section. Trace the diagnostic for applying @Int to an inferred {a} argument; done means the error explains the extension, the inferred-versus-specified distinction, and possible alternatives, with the reproducer producing the improved wording.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
compilers
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.