tomjaguarpaw / tilapia

Improving all Haskell's programmer interfaces

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to get VSCode to recognize a dependency

goldfirere opened this issue · comments

I have a Haskell file in VSCode with import Data.Vector. VSCode suggests to me that perhaps I want Data.Functor. But, no, I want Data.Vector.

How can I get VSCode/HLS to recognize the vector package? I added a .cabal file, but that doesn't seem to make a difference. I don't even know where to post this! Is it an HLS issue? A VSCode issue? A cabal issue? A GHC issue?

Help?

I somehow was able to find these instructions: https://www.reddit.com/r/haskellquestions/comments/mwi9pm/haskell_language_server_not_recognizing_imports/. Evidently, I need to install an executable from a package implicit-hie and then chant gen-hie > hie.yaml. I tried this and -- mirabile dictu -- it worked. I have no idea why this works or really what it does. Interestingly, the hie.yaml file makes no mention of vector (though, of course, my .cabal file does).

Oh, and what is HIE?

It's becoming clearer this is really more appropriate on the HLS bug tracker. But I'll see if I get any comments here before replaying this there.

In any case, I'm happily unstuck.

I partied too soon. It turns out that the error is still here, but it just moved.... and became more inscrutable. I have

Multi Cradle: No prefixes matched
pwd: /Users/rae/Dropbox/work/tweag/video-resources/2021-10-06-patsyns4
filepath: /Users/rae/Dropbox/work/tweag/video-resources/2021-10-06-patsyns4/VecUnsafe.hs
prefixes:
("./Main.hs",Cabal {component = Just "patsyns4:exe:patsyns4"})
cradle
Multi Cradle: No prefixes matched
pwd: /Users/rae/Dropbox/work/tweag/video-resources/2021-10-06-patsyns4
filepath: /Users/rae/Dropbox/work/tweag/video-resources/2021-10-06-patsyns4/VecUnsafe.hs
prefixes:
("./Main.hs",Cabal {component = Just "patsyns4:exe:patsyns4"})
cradle

I'm now getting more lost, because I don't know what a cradle is or how to rock one.

Searching for "Multi Cradle: No prefixes matched" got me to haskell/haskell-language-server#1215, which is in the same area, but not exactly my problem. This bug report, though, links to https://github.com/haskell/haskell-language-server#configuring-your-project-build, which looks very promising. Sadly, the anchor doesn't exist anymore. :(

It's not that hard to find my way to https://haskell-language-server.readthedocs.io/en/latest/configuration.html#configuring-your-project-build instead. This information is helpful, saying things like HLS will work out of the box "for most use cases". Good. Except it's not working for me, and I'm starting to doubt the claim, because my use-case seems really very simple. In any case, I'm linked to hie-bios for more information. So I follow the trail to https://github.com/haskell/hie-bios/blob/master/README.md

This page tells me that my hie.yaml file should be just

cradle:
  cabal:

This is different than what gen-hie gave me. So I edit my hie.yaml file accordingly.

Now I get this error:

Failed to parse result of calling cabal

cabal: Unknown target
'/Users/rae/Dropbox/work/tweag/video-resources/2021-10-06-patsyns4/VecUnsafe.hs'.
The package patsyns4 has no file target 'VecUnsafe.hs'.




cradle
Failed to parse result of calling cabal

cabal: Unknown target
'/Users/rae/Dropbox/work/tweag/video-resources/2021-10-06-patsyns4/VecUnsafe.hs'.
The package patsyns4 has no file target 'VecUnsafe.hs'.




cradle

I'm intrigued by "The package patsyns4 has no file target 'VecUnsafe.hs'.". Given my decade of Haskell programming experience, I wonder if this means I need to add VecUnsafe (the file I'm trying to compile in VSCode) to my .cabal file. (Specifically, I happen to know that I should have other-modules: VecUnsafe.)

This does not solve my problem. But, taking the very fine advice from
image, I stop and start the HLS.

This now gets me unstuck, I think. My VecUnsafe module is working. Now, though, I have errors in all my other modules, because they are not listed in my .cabal file. Urgh. I will add them. What's unfortunate is that I'm really at an early stage of tinkering here, and I don't know what modules I will want in the end. It's quite annoying having to update the .cabal file every time I restructure things. I remember the good old days, when I would take an error along the lines of module Data.Vector not found and say cabal install vector (this was v1 days, when installing libraries just worked -- until it didn't due to cabal hell) and then restart GHCi and be off to the races. It's really quite sad that I now need a .cabal file (which, incidentally, also produces a CHANGELOG and a LICENSE) and a hie.yaml file, and to keep this in proper working order, just to be able to find the vector package in my editor. Maybe, if I'm lacking a .cabal file, HLS should just make all system packages available somehow? Or maybe we don't even have system packages anymore...

Hi, thanks for describing your periplus. Like the other issue, lot of insights arise watching the process with new eyes.

I don't even know where to post this! Is it an HLS issue? A VSCode issue? A cabal issue? A GHC issue?

It's becoming clearer this is really more appropriate on the HLS bug tracker. But I'll see if I get any comments here before replaying this there.

I think the issue could be opened in hls, even if it ends to be a question and probably a documentation enhancement. You have experienced the issue through hls and i believe it should be the starting point to trace it.

How can I get VSCode/HLS to recognize the vector package? I added a .cabal file, but that doesn't seem to make a difference.

Could you describe your actual workspace structure and config files (a link would be great)?

I think the root causes of the perplexity are:

  • hls relies on cabal or stack to being able to load a package or project. Nowadays cabal and its new build system (v2) privileges the project centric approach and ask you for a .cabal (and maybe cabal.project) file by default. You can recover somewhat the workflow of the old build system using the new one tweaking some cli options or directly using it while it is not removed (you will need to do a cabal v1-install, as you already suspected). You can see what are the actual plan to recover the v1 workflow here: haskell/cabal#6481
  • With no project/package config info hls uses directly ghc to load files. Specifically it uses ghc --interactive (aka ghci). It is an implementation detail which is about to change and users should not know it of course. But that means if you can load the file with ghci hls should load the file too. It means it will not be able to load a module with external dependencies by default (like in your case). But this should work (as you already suspected?):
cabal v1-install vector
code ModuleUsingVector.hs
  • Really hie.yaml is not needed for most use cases, believe the official docs 😉:. Adding it likely will not help to be unstuck but make things worse (like in this case). Unfortunately it was needed at some point of the history of the predecessors of haskell-language-server: haskell-ide-engine and ghcide. The web is still plenty of references to 😟 . gen-hie needs a working .cabal file to generate a good hie.yaml file and that was just what you needed at that point.
  • hls is not reloading the project when cabal/stack config changes and you need to restart it manually. That is very sad from a usability point of view and used to work but good news is we have a issue about 😛 haskell/haskell-language-server#1068

consider this shell session:

  • ghci is not able to load the module as it does not know where the hell Data.Vector is
D:\ws\haskell\issues\empty>type MyModule.hs
module MyModule where

import Data.Vector

main = putStrLn "Hi hls"


D:\ws\haskell\issues\empty>ghci MyModule
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling MyModule         ( MyModule.hs, interpreted )

MyModule.hs:3:1: error:
    Could not find module ‘Data.Vector’
��
    Perhaps you meant Data.Functor (from base-4.12.0.0)
    Use -v to see a list of the files searched for.
  |
3 | import Data.Vector
  | ^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
Prelude> :q
  • so hls, which uses ghc for standalone files neither know how to make the impor work (it will show the error in the editor though and even it will suggest you to change it with Data.Functor, not very hepful in this case). We can use hls in the cli to check quickly if files will be loaded in the editor
D:\ws\haskell\issues\empty>haskell-language-server-wrapper MyModule.hs
No 'hie.yaml' found. Try to discover the project type!
Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper-1.4.0.exe) Version 1.4.0.0, Git revision 253547816ee216c53ee7dacc0ad3cac43e863d3
0 (dirty) x86_64 ghc-8.10.4
Current directory: D:\ws\haskell\issues\empty
Operating system: mingw32
Arguments: ["MyModule.hs"]
Cradle directory: D:\ws\haskell\issues\empty
Cradle type: Default

Tool versions found on the $PATH
cabal:          3.4.0.0
stack:          2.7.3.1
ghc:            8.6.5


Consulting the cradle to get project GHC version...
Project GHC version: 8.6.5
haskell-language-server exe candidates: ["haskell-language-server-8.6.5.exe","haskell-language-server.exe"]
Launching haskell-language-server exe at:D:\ghcup\bin\haskell-language-server-8.6.5.exe
haskell-language-server version: 1.4.0.0 (GHC: 8.6.5) (PATH: D:\ghcup\bin\haskell-language-server-8.6.5~1.4.0.exe) (GIT hash: 253547816ee216c53ee7dacc0ad3cac43e863d30)
 ghcide setup tester in D:\ws\haskell\issues\empty.
Report bugs at https://github.com/haskell/haskell-language-server/issues

Step 1/4: Finding files to test in D:\ws\haskell\issues\empty
Found 1 files

Step 2/4: Looking for hie.yaml files that control setup
Found 1 cradle
  ()

Step 3/4: Initializing the IDE

Step 4/4: Type checking the files
2021-10-06 09:11:04.0434376 [ThreadId 31] INFO hls:     Consulting the cradle for "MyModule.hs"
2021-10-06 09:11:04.0434376 [ThreadId 31] WARNING hls:  No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for MyModule.hs.
 Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
*You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.*
Output from setting up the cradle Cradle {cradleRootDir = "D:\\ws\\haskell\\issues\\empty", cradleOptsProg = CradleAction: Default}
2021-10-06 09:11:04.9234904 [ThreadId 31] INFO hls:     Using interface files cache dir: C:\Users\user\AppData\Local\ghcide\main-da39a3ee5e6b4b0d3255bfef95601890afd80709
2021-10-06 09:11:04.9234904 [ThreadId 31] INFO hls:     Making new HscEnv[main]
2021-10-06 09:11:05.0134958 [ThreadId 67] INFO hls:     File:     D:\ws\haskell\issues\empty\MyModule.hs
Hidden:   no
Range:    3:8-3:19
Source:   not found
Severity: DsError
Message:  Could not find module ‘Data.Vector’Perhaps you meant Data.Functor (from base-4.12.0.0)0)
2021-10-06 09:11:05.0634988 [ThreadId 72] INFO hls:     finish: User TypeCheck (took 0.13s)
Files that failed:
 * D:\ws\haskell\issues\empty\MyModule.hs

2021-10-06 09:11:05.0634988 [ThreadId 74] INFO hls:     finish: GetHie (took 0.00s)
Completed (0 files worked, 1 file failed)
2021-10-06 09:11:05.0734994 [ThreadId 76] INFO hls:     finish: GenerateCore (took 0.00s)
haskell-language-server-wrapper-1.4.0.exe: callProcess: D:\ghcup\bin\haskell-lan
guage-server-8.6.5.exe "MyModule.hs" (exit 1): failed
  • Ok so we still could use the cabal new build system to install and make available dependencies for raw ghc:
D:\ws\haskell\issues\empty>cabal install vector --lib --package-env .
Resolving dependencies...
Build profile: -w ghc-8.6.5 -O1
In order, the following will be built (use -v for more details):
 - primitive-0.7.2.0 (lib) (requires build)
 - vector-0.12.3.0 (lib) (requires build)
Configuring library for primitive-0.7.2.0..
Preprocessing library for primitive-0.7.2.0..
Building library for primitive-0.7.2.0..
[ 1 of 13] Compiling Control.Monad.Primitive ( Control\Monad\Primitive.hs, dist\
build\Control\Monad\Primitive.o )
....................
[13 of 13] Compiling Data.Primitive   ( Data\Primitive.hs, dist\build\Data\Primi
tive.o )
Installing library in D:\csd\ghc-8.6.5\incoming\new-10784\csd\ghc-8.6.5\primitiv
e-0.7.2.0-2217ba418fdffdc3dedf8d328f65a15af78ec7d3\lib
Configuring library for vector-0.12.3.0..
Preprocessing library for vector-0.12.3.0..
Building library for vector-0.12.3.0..
[ 1 of 21] Compiling Data.Vector.Fusion.Util ( Data\Vector\Fusion\Util.hs, dist\
build\Data\Vector\Fusion\Util.o )
.................
[21 of 21] Compiling Data.Vector.Unboxed.Mutable ( Data\Vector\Unboxed\Mutable.h
s, dist\build\Data\Vector\Unboxed\Mutable.o )
Installing library in D:\csd\ghc-8.6.5\incoming\new-10784\csd\ghc-8.6.5\vector-0
.12.3.0-890f19f08693e36de87af19c8e32805b50f5c52a\lib
  • It creates a ghc package environment file telling ghc where the dependencies are inside the cabal global store cache. ghc will use it by default if it is placed in the current working dir
D:\ws\haskell\issues\empty>type .ghc.environment.x86_64-mingw32-8.6.5
clear-package-db
global-package-db
package-db D:\csd\ghc-8.6.5\package.db
package-id ghc-8.6.5
package-id bytestring-0.10.8.2
package-id base-4.12.0.0
package-id time-1.8.0.2
package-id hpc-0.6.0.3
package-id filepath-1.4.2.1
package-id process-1.6.13.2-ec46251422ad48c2a8cc61cf651593cfc24378db
package-id array-0.5.3.0
package-id integer-gmp-1.0.2.0
package-id containers-0.6.0.1
package-id ghc-boot-8.6.5
package-id binary-0.8.6.0
package-id ghc-prim-0.5.3
package-id ghci-8.6.5
package-id rts
package-id transformers-0.5.6.2
package-id deepseq-1.4.4.0
package-id ghc-boot-th-8.6.5
package-id pretty-1.1.3.6
package-id template-haskell-2.14.0.0
package-id directory-1.3.3.0
package-id text-1.2.3.1
package-id vector-0.12.3.0-890f19f08693e36de87af19c8e32805b50f5c52a

D:\ws\haskell\issues\empty>ghci MyModule.hs
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Loaded package environment from D:\ws\haskell\issues\empty\.ghc.environment.x86_64-mingw32-8.6.5
[1 of 1] Compiling MyModule         ( MyModule.hs, interpreted )
Ok, one module loaded.
  • So now hls also knows Data.Vector is in scope
D:\ws\haskell\issues\empty>haskell-language-server-wrapper MyModule.hs
No 'hie.yaml' found. Try to discover the project type!
Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper
1.4.0.exe) Version 1.4.0.0, Git revision 253547816ee216c53ee7dacc0ad3cac43e863d
0 (dirty) x86_64 ghc-8.10.4
Current directory: D:\ws\haskell\issues\empty
Operating system: mingw32
Arguments: ["MyModule.hs"]
Cradle directory: D:\ws\haskell\issues\empty
Cradle type: Default

Tool versions found on the $PATH
cabal:          3.4.0.0
stack:          2.7.3.1
ghc:            8.6.5


Consulting the cradle to get project GHC version...
Project GHC version: 8.6.5
haskell-language-server exe candidates: ["haskell-language-server-8.6.5.exe","hskell-language-server.exe"]
Launching haskell-language-server exe at:D:\ghcup\bin\haskell-language-server-86.5.exe
haskell-language-server version: 1.4.0.0 (GHC: 8.6.5) (PATH: D:\ghcup\bin\haskel-language-server-8.6.5~1.4.0.exe) (GIT hash: 253547816ee216c53ee7dacc0ad3cac43863d30)
 ghcide setup tester in D:\ws\haskell\issues\empty.
Report bugs at https://github.com/haskell/haskell-language-server/issues

Step 1/4: Finding files to test in D:\ws\haskell\issues\empty
Found 1 files

Step 2/4: Looking for hie.yaml files that control setup
Found 1 cradle
  ()

Step 3/4: Initializing the IDE

Step 4/4: Type checking the files
2021-10-06 09:20:54.9949884 [ThreadId 27] INFO hls:     Consulting the cradle fr "MyModule.hs"
2021-10-06 09:20:54.9949884 [ThreadId 27] WARNING hls:  No [cradle](https://gitub.com/mpickering/hie-bios#hie-bios) found for MyModule.hs.
 Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicithie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes mathed' error.
Output from setting up the cradle Cradle {cradleRootDir = "D:\\ws\\haskell\\isses\\empty", cradleOptsProg = CradleAction: Default}
Loaded package environment from D:\ws\haskell\issues\empty\.ghc.environment.x8664-mingw32-8.6.5
2021-10-06 09:20:55.7249665 [ThreadId 27] INFO hls:     Using interface files cche dir: C:\Users\user\AppData\Local\ghcide\main-da39a3ee5e6b4b0d3255bfef9560189afd80709
2021-10-06 09:20:55.7249665 [ThreadId 27] INFO hls:     Making new HscEnv[main]
2021-10-06 09:20:56.0469578 [ThreadId 64] INFO hls:     finish: User TypeChecktook 0.27s)
2021-10-06 09:20:56.0769569 [ThreadId 67] INFO hls:     finish: GetHie (took 0.3s)
2021-10-06 09:20:56.1269554 [ThreadId 64] INFO hls:     finish: GenerateCore (tok 0.04s)

Completed (1 file worked, 0 files failed)

D:\ws\haskell\issues\empty>code MyModule.hs
  • and you get your module succesfully loaded

imagen

Caveats: cabal install --lib is dangerous so i will not suggest use it to beginners. It creates by default ghc package env files in a globa location and ghc will use them always. It likely will drive to obscure errors in other files which need other versions of deps and will havoc cabal/stack builds for projects.
So there are plans to deprecate it and create a new cabal command cabal env to manage specifically those files.

@jneira So helpful! Thank you!

Let me summarize the parts here that I found most helpful:

  • I should report future struggles to HLS directly. I will do so.
  • You described a process by which HLS tries to understand a Haskell file. It sounds like it goes something like this: First, check for a .cabal file. If present, use it, with cabal repl. Next, check for a stack.yaml file. If present, use it, with stack repl. Otherwise, try to load the file in GHCi. This little algorithm is really helpful to state somewhere, because it allows me to reduce my "HLS isn't working" problem to a sequence of command-line invocations I can understand independently.
  • Don't use hie.yaml. It might be helpful to edit pages that refer to to hie.yaml to say that you really shouldn't need this.
  • Use cabal-env. Indeed, I can verify that this works for me.

What's interesting is that I tested my understanding by creating a separate project that needed a package dependency. HLS failed to find the package (as expected). I then added a bare-bones .cabal file that included the right dependency. My experience last night suggested this wouldn't work. But -- with a restart of HLS and a little patience -- it did! So, maybe my critical error last night was not restarting HLS at precisely the right moment. Or maybe I made other mistakes.

I'm now trying to come up with concrete suggestions of improvements to help the next person. Here are a few thoughts:

  • https://haskell-language-server.readthedocs.io/en/latest/troubleshooting.html may want to include the little algorithm above, suggesting that users try to load their files directly at the command line to see if they learn anything of interest.
  • That page should also recommend restarting HLS.
  • That page tells me to run haskell-language-server. But (to my surprise) I don't have this in my PATH. I think HLS got installed as part of the VSCode extension. I suppose I could install it in my PATH separately, but then I'm worried about having two different HLSs -- perhaps with different versions -- on my system. So maybe the VSCode extension should add haskell-language-server to my PATH (or ask me if I want this, or tell me where the binary is)
  • Maybe best of all: if an import is unknown, the error message should suggest adding a .cabal file with dependencies. Even better: HLS could provide a code action that either creates the .cabal file (if it doesn't exist) or add a dependency if the .cabal file does exist. Even better: HLS should maintain some database mapping module names to packages (built by slurping the data off Hackage every now and then) to suggest concrete package names. That would be fantastic: I would write import Wiz.Woz in my file, and then I get a code action saying "Add a dependency on wizwoz-0.2.12 to your .cabal file"... with a configuration option for how tight I want my default version bounds to be.

It would be good to explain the implicit discovery of the project type/tool.
However the use of the repl command is an implementation detail that will be changed in a no too distant future.

  • That page should also recommend restarting HLS.

I was reluctant to recommend it in docs cause i think we must fix all the root causes of having to restart the ide. But it is good for usersto know when they have to do it for sure. We have to update the troubleshooting section to reflect more recent issues.

  • That page tells me to run haskell-language-server. But (to my surprise) I don't have this in my PATH. I think HLS got installed as part of the VSCode extension. I suppose I could install it in my PATH separately, but then I'm worried about having two different HLSs -- perhaps with different versions -- on my system. So maybe the VSCode extension should add haskell-language-server to my PATH (or ask me if I want this, or tell me where the binary is)

mmm other users has hit the same issue. Not sure if set the downloaded executable in PATH would be the the best option though. Other one could be execute the downloaded hls in the project root, gather the info and automatically open an issue with all the known info in the hls repo, including os, tool versions and the the output.

  • Maybe best of all: if an import is unknown, the error message should suggest adding a .cabal file with dependencies. Even better: HLS could provide a code action that either creates the .cabal file (if it doesn't exist) or add a dependency if the .cabal file does exist. Even better: HLS should maintain some database mapping module names to packages (built by slurping the data off Hackage every now and then) to suggest concrete package names. That would be fantastic: I would write import Wiz.Woz in my file, and then I get a code action saying "Add a dependency on wizwoz-0.2.12 to your .cabal file"... with a configuration option for how tight I want my default version bounds to be.

Agree that would be the optimal solution, we have an old issue about haskell/haskell-language-server#155

It would be good to explain the implicit discovery of the project type/tool. However the use of the repl command is an implementation detail that will be changed in a no too distant future.

That's fine if the algorithm changes -- but it should probably be stated somewhere, because things will go wrong sometimes. Equipped with the knowledge of the algorithm, I am then empowered to explore further and learn more about where things are going wrong.

  • That page should also recommend restarting HLS.

I was reluctant to recommend it in docs cause i think we must fix all the root causes of having to restart the ide. But it is good for usersto know when they have to do it for sure. We have to update the troubleshooting section to reflect more recent issues.

For better or worse, I have discovered that I fairly often have to restart HLS -- basically, whenever I do something other than edit a Haskell file (e.g. add new files, rename files, delete files, edit dependencies, install new system packages, etc.). I agree it would be better not to have to do this, but I doubt it will never be necessary -- given that we all sometimes have to restart software created by very well-funded corporations.

mmm other users has hit the same issue. Not sure if set the downloaded executable in PATH would be the the best option though. Other one could be execute the downloaded hls in the project root, gather the info and automatically open an issue with all the known info in the hls repo, including os, tool versions and the the output.

I don't understand what you mean here, but allowing me to quickly open an issue sounds great.

issue about opening an issue automatically: haskell/vscode-haskell#482