haskell-language-server
haskell-language-server copied to clipboard
Inlay hints usage
In order to prevent spam, I open a thread to discuss about the inlay hint usage in Haskell.
Previous info is here: https://github.com/haskell/haskell-language-server/issues/2019#issuecomment-1144502854
lsp-3.17 had supported inlay hint, in which can embed some useful info, it wildly used by displaying function parameter names in other languages. But it is not suitable in Haskell since Haskell have a lot of currying, which looks not valid to display parameter name in Haskell.
Sample of inlay hint:
I don't want Haskell missing this straightforward function, so I wrote these to discuss what we can do to use inlay hint best, here are some I'd like:
- Show type signature for let expressions
f = let g {- inlay hint here, should be `:: Bool` -}= True
in g
- Show operator fixity as mentioned in https://github.com/haskell/haskell-language-server/issues/2019#issuecomment-1144499665
All these are initial ideas for discussion, feel free to put forward any suggestions:)
+1 for let bindings.
I'd have to see what the fixity one actually looks like, but in my head it seems like overload.
+1 for let bindings too
Can we use this to show the implicit imports list, instead of a code lens?
Can we use this to show the implicit imports list, instead of a code lens?
Not sure, I haven't seen any inlay hint in a new line. But is there any shortcoming for code lens?
The idea is to show the implicit imports list inline, not in a new line. We have wanted this for a while:
https://github.com/haskell/haskell-language-server/issues/426#issuecomment-698216817
Note that inlay hints aren't supported by the lsp
library yet. I'm working on generating the types from the new machine-readable version, which will hopefully include this, but it may be a while.
More ideas
Type signatures
Lambda arguments? i.e.
\x {- :: Int -} -> ...
Function arguments? i.e.
foo x {- :: Int -}
(probably not, a bit redundant with the main type signature?)
Bindings in do blocks? i.e.
x {- :: Int -} <- ...
These are all really special cases of "put an inlay hint every time a variable is bound without a type signature", but I think that would probably be too much in many cases. But might be worth trying to see if it's unbearable! Maybe the general case is what we want.
Implicit names
Record wildcards?
x{... {- foo, bar, baz -}}
An explicit imports inlay hint is arguably an example of this!
Misc
Record names in positional record construction?
MyRec {- foo= -} a {- bar= -} b {- baz= -} c
These are all really special cases of "put an inlay hint every time a variable is bound without a type signature", but I think that would probably be too much in many cases. But might be worth trying to see if it's unbearable! Maybe the general case is what we want.
I can see someone wanting to keep some of the inlay hints but not all (myself included). Is this something we want to allow to be configurable? Or should we aim for a minimum case first (i.e. just let bindings and lambdas for example) and go from there?
Ideally we don't configure things too much, but we might want a "noisy" version and a "quiet" version, perhaps.
I think the observation about the general case is more for design thinking: I'm not sure I have a good rationale for why some places that introduce a name without a type signature should get inlay hints and some shouldn't. So what's our heuristic?
Agree @michaelpj 's ideas, just one thought, I prefer to show function parameters' name instead of their type. (Although not beautiful to look at)
I still believe it's not bad to have more configure, it has little effect for most users(they won't touch these settings)
Here is some configuration(partial) for TypeScript.

Here is some configuration(partial) for Rust.

Also maybe holes: https://github.com/haskell/haskell-language-server/issues/3228
I think all our code lenses that display signatures should be inlay hints also: https://github.com/haskell/haskell-language-server/issues/3254
Out of curiosity, what is the current status of the inlay hints support of lsp
library?
It'll be there once I finish https://github.com/haskell/lsp/pull/458 :sweat_smile:
It'll be there once I finish haskell/lsp#458 😅
@michaelpj I noticed the linked issue was closed in favor of another one that is now merged. Do you know how long until that will land in a release?
Support in the library has been there for a while now, now someone just actually needs to implement using them in HLS.
Another idea: show inferred deriving strategies and allow clicking on them to make them explicit.
HI, guys. I think I've made some progress #4131. I successfully display fixity info via inlay hints, there's still a lot of work to do :)
If you're looking for ideas:
Related to fixity - what about inserting parentheses? So a * b + c / d
gains inlay hints (a * b) + (c / d)
in accordance with fixity (I might be remembering this from some other IDE, not sure)
Along the lines of https://github.com/haskell/haskell-language-server/issues/2938#issuecomment-1908241896 there's other implicit stuff that could be wrong, like type roles, defaulted instances e.g. in show . read
, overloaded list/string syntax, defaulted method implementations.
Some less clear ideas - with LinearTypes it might be useful to see info about usage (e.g. let %1 inference coming in 9.10), I also wonder if there's any useful information that could be shown for analysing performance like where allocations can occur or rules can fire or what is still lazy in O2 or something.
A kind of obvious one that I've mentioned to some people before but not written down: our import lenses. At the moment they are code lenses and they take up a whole extra line per-import. But since they are precisely suggesting extra changes to the import line, we could instead have them be inlay hints, which would mean they only take up one line.
i.e.
import Foo <hint begins>(Bar, Baz)<hint ends>
rather than
<lens> import Foo (Bar, Baz)
import Foo
(https://github.com/haskell/haskell-language-server/issues/4208)
(We're going to try and split out individual issues for the individual ideas)
Hello @michaelpj! Just found this on GSoC and would be willing to contribute. I have an intermediate experience with Haskell, as an independent learner. I use HLS on Emacs, so I'd like to give back in whatever way possible. I'm not a traditional university student though, hopefully that is not an issue.
As the project mentions you as the mentor, would you be willing to guide me in how to get started with this?
Regards,
Divya.
@jetjinser is the GSoC student for this, so I think the plan is for them to focus on it for now.
Oh, didn't know this was already being worked upon. Apologies.