HLS必须与GHC版本严格匹配,否则静默失效;应使用ghcup install hls 9.6.4指定版本,配置VSCode的haskell.serverExecutablePath为精确二进制路径(如haskell-language-server-9.6.4),并确保打开含.cabal或stack.yaml的项目根目录。

HLS 必须手动安装且与 GHC 版本严格匹配,VSCode 的 Haskell 插件不会自动帮你装对版本,装错就直接静默失效——没有报错,只有悬停无类型、跳转失败、波浪线消失。
为什么 haskell-language-server 总是“找不到”或“不工作”
VSCode 的 Haskell 插件(ID: Haskell.haskell)本身不带 haskell-language-server 二进制,它只负责调用。而 HLS 不是通用可执行文件,每个 GHC 版本对应一个编译好的 HLS 实例(例如 GHC 9.6.4 → haskell-language-server-9.6.4)。常见失效原因:
- 用
ghcup install hls但没指定版本,结果装了默认最新版,却和当前ghc --version不兼容 - PATH 里有多个 HLS 可执行文件,VSCode 拿到的是错版本的 wrapper 或旧缓存路径
- 项目根目录下没
.cabal或stack.yaml,HLS 启动后因无法识别项目结构而退化为“单文件模式”,类型检查能力大幅缩水 - macOS 上用了 Homebrew 安装的
ghc,但ghcup安装的 HLS 绑定的是 ghcup 自己装的 GHC,两者 runtime 不互通
用 ghcup 装对版本的 haskell-language-server
先确认你实际在用的 GHC 版本:
ghc --version
假设输出是 The Glorious Glasgow Haskell Compilation System, version 9.6.4,那就必须装对应 HLS:
- 运行
ghcup install hls 9.6.4(不是ghcup install hls) - 再运行
ghcup set hls 9.6.4,确保haskell-language-server命令指向该版本 - 验证:执行
haskell-language-server --version,输出末尾应含ghc-9.6.4 - 别依赖
which haskell-language-server的路径——它可能指向 wrapper;真正要用的是which haskell-language-server-9.6.4
VSCode 中正确配置 haskell.serverExecutablePath
插件默认尝试调用 haskell-language-server,但在多版本共存时极易出错。最稳的方式是指定精确二进制路径:
- 在 VSCode 中按
Cmd+,打开设置 → 搜索 “Haskell: Server Executable Path” → 点击 “Edit in settings.json” - 填入完整路径,例如:
"haskell.serverExecutablePath": "/Users/yourname/.ghcup/bin/haskell-language-server-9.6.4" - 注意:不是
haskell-language-server-wrapper,也不是haskell-language-server(那个只是 shell wrapper) - 改完保存,**必须关闭并重新打开整个 VSCode 窗口**(仅重启窗口不够,LSP 进程会残留)
验证 HLS 是否真正在工作
光看语法高亮没用。真正有效的验证方式只有三个动作,缺一不可:
- 打开一个带
import Data.Text的.hs文件,等待几秒 —— 如果左下角状态栏出现 “HLS: Ready”,说明连接成功 - 把鼠标悬停在
putStrLn上,应该立刻显示String -> IO ();悬停在自定义函数上也应显示类型 - 故意写错类型,比如
main = putStrLn 42,应立刻在42下出现红色波浪线,并提示 “Couldn't match expected type ‘String’ with actual type ‘Integer’” - 如果以上任一失败,优先检查
haskell-language-server-9.6.4 --probe-tools输出是否全绿;若显示fourmolu或brittany缺失,HLS 仍能运行,但格式化会挂,类型检查不受影响
最容易被忽略的一点:HLS 启动依赖项目根目录下的构建元数据。如果你只是用 VSCode 打开单个 Main.hs 文件而没打开整个含 .cabal 的文件夹,HLS 会降级为“无项目模式”,很多跨模块类型推导和补全就直接失效——这不是 bug,是设计使然。



















