A lot of work has gone into making GHC able to produce suggestions and the current code action falls short of making the most of it. The possibilities include:
-fshow-hole-constraints to make added constraints explicit?-fshow-docs-of-hole-fits to show the docs of the suggestion?-frefinement-level-hole-fits=1 to show almost-valid fits?-fsort-by-subsumption-hole-fits ?This is a candidate good first issue @ndmitchell @cocreature
Further discussion in this Reddit thread
ping @tritlo
Refinements hole fits are valid! They just need additional arguments. A very nice developer flow would be to add those suggestions as well, and then users can fill holes with functions with additional holes!
I wouldn't suggest sort by subsumption. It only gives slightly better order, but it is much slower (especially when there's lots of matches.
Show constraints is the best, since you can tell at a glance what's happening. Though it doesn't work without TypeApplications on (since the resulting @ would be a parse error).
Showing the docs would be nice too, though it can produce a lot of output if the docs are long!
noob question:
Should it use -fshow-hole-constraints to make added constraints explicit?
Do you mean that if there is a suggestion of, for example, mempty, in the list of quickfix, we should show this value is from Monoid typeclass?
I'm confused because constraints shown don't seem bound on specific suggestions
For example:
Main.hs:8:5: error:
• Found hole: _ :: a
Where: ‘a’ is a rigid type variable bound by
the type signature for:
f :: forall a. Monoid a => a
at Main.hs:7:1-18
• In the expression: _
In an equation for ‘f’: f = _
• Relevant bindings include f :: a (bound at Main.hs:8:1)
Constraints include Monoid a (from Main.hs:7:1-18) <------------- this line
Valid hole fits include
f :: a (bound at Main.hs:8:1)
mempty :: forall a. Monoid a => a
with mempty @a
(imported from ‘Prelude’ at Main.hs:3:1-14
(and originally defined in ‘GHC.Base’))
Looks like -fshow-hole-constraints doesn't do anything useful for ghcide.
Another thing that could be very useful would be to not suggest trivial infinite recursion.
If I write the code
foobar :: Foo -> Bar
foobar = _
I probably don't want the definition
foobar :: Foo -> Bar
foobar = foobar
Currently, this is the first suggestion it gives.
Maybe I should open a separate issue for that though?
Yet another thing that might be very useful, but maybe is much work (including more work on ghc), would be the ability to fill holes with a function that require more arguments, which would then become new holes.
E.g.
example :: Maybe String
example = _
which it would suggest filling with either Nothing or Just _.
example :: Maybe String
example = Just _
This particular case could also be resolved as introduction forms for the data type, but I was thinking of a more general version for arbitrary functions.
These suggestions should probably be lower down in the list than the more precise suggestions. And it probably shouldn't suggest generic functions like id and other things with a return value of SomeConstraint a => a.
Yet another thing that might be very useful, but maybe is much work (including more work on ghc), would be the ability to fill holes with a function that require more arguments, which would then become new holes.
E.g.
example :: Maybe String example = _which it would suggest filling with either
NothingorJust _.example :: Maybe String example = Just _This particular case could also be resolved as introduction forms for the data type, but I was thinking of a more general version for arbitrary functions.
These suggestions should probably be lower down in the list than the more precise suggestions. And it probably shouldn't suggest generic functions like
idand other things with a return value ofSomeConstraint a => a.
This is precisely what -frefinement-level-hole-fits=1 does
Most helpful comment
This is precisely what
-frefinement-level-hole-fits=1does