单文件快速验证用 runhaskell,需变量保持、多步交互或调试时必须用 ghci;vscode 依赖系统命令执行,二者本质不同:runhaskell 是一次性脚本解释器,ghci 是带项目上下文的 repl 环境。

VSCode里runhaskell和ghci到底该用哪个
单文件快速验证用 runhaskell,需要变量保持、多步交互或调试时必须用 ghci。VSCode 自身不内置执行逻辑,所有“运行”行为都靠调用系统命令触发——runhaskell 是一次性的脚本解释器,ghci 才是真正的 REPL 环境。
常见误判:点了“运行”没反应,就以为是插件问题。其实大概率是终端里根本找不到 runhaskell 或 ghci,或者当前工作目录不是项目根(导致模块路径解析失败)。
-
runhaskell适合:语法练习、小工具脚本、无 import 或仅用 base 的单文件 -
ghci必须用在项目上下文中:有.cabal或stack.yaml,且已执行过cabal build或stack build,否则会报Could not find module - VSCode 集成终端中手动运行
ghci失败?先检查echo $PATH(Linux/macOS)或$env:PATH(PowerShell),确认~/.ghcup/bin(或 Windows 的C:\ghcup\bin)已生效
为什么ghci在VSCode里加载慢、补全卡顿
HLS 和 ghci 是两套机制:HLS 负责编辑时的类型推导和跳转,ghci 负责运行时求值。但 VSCode 的 Haskell 插件默认会尝试用 HLS 启动一个“带类型信息的 ghci”,这就要求两者 GHC 版本完全一致,且 ghci 加载的包必须与项目 build-depends 对齐。
典型症状:打开 ghci 后长时间卡在 Loading package environment...,或输入 :t map 没响应。
- 确保
ghci启动时用了项目配置:在项目根目录下运行cabal repl或stack ghci,而不是裸跑ghci - 别在空目录或只含
Main.hs的目录里开ghci——它找不到依赖上下文,只能加载 base,其他模块全报错 - 如果用了
stack,但.stack-work/是空的,stack ghci会先花几十秒重建环境;提前运行一次stack build可避免每次启动都卡住 - HLS 缓存污染也会拖慢
ghci初始化:删掉~/.cache/haskell-language-server/(Linux/macOS)或%LOCALAPPDATA%\haskell-language-server\(Windows)再试
如何让VSCode的Haskell插件真正接管ghci交互
默认情况下,VSCode 的 Haskell 插件只提供“启动 ghci”按钮,但不接管输入/输出流——你得自己切到集成终端敲命令。要获得类似 IDE 的交互体验(比如选中表达式后 Ctrl+Enter 直接求值),必须启用插件的 repl 功能并确保底层链路通畅。
关键不是装插件,而是让插件能拿到一个“活的、带项目上下文的 ghci 进程”。
- 插件设置中开启
haskell.replEnabled(默认为 true),但前提是 HLS 已就绪:右下角状态栏显示HLS ready (ghc-9.6.4) - 必须用
File → Open Folder打开含.cabal或stack.yaml的目录,且该目录下已有可构建的代码(哪怕只是module Main where) - 若用
cabal,建议在项目根加一个.ghci文件,内容为::set -XOverloadedStrings\n:set -Wall\n:load Main
,这样cabal repl启动时自动加载主模块 - Windows 用户注意:PowerShell 默认策略可能阻止
ghci启动,临时运行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser即可
Ctrl+Enter求值失败的三个硬性条件
VSCode 里选中一段代码按 Ctrl+Enter 想直接在 ghci 中求值,结果弹出错误或静默失败——这不是功能坏了,而是三个前置条件没满足:
- 光标必须落在合法的 Haskell 表达式上(不能在注释、字符串字面量、模块声明行内)
- 当前文件必须已保存,且属于当前打开项目的模块树(即被
.cabal的other-modules或exposed-modules引用,或在stack.yaml的packages列表中) - HLS 进程必须处于活跃状态,并且已成功加载该项目的接口(观察输出面板 “Haskell” 标签页,应有
Run entered for haskell-language-server-*且无 ERROR 日志)
最容易被忽略的是第二点:新建一个 Utils.hs,写了函数但没在 .cabal 里声明,Ctrl+Enter 就一定失败——HLS 根本不知道这个文件属于项目,更不会把它喂给 ghci。











