Haskell Stack工作流机制及REPL使用、全局GHCi配置方法
Stack本质是Haskell生态面向项目的依赖隔离与构建一致性工具,核心解决的是早期Cabal全局装包容易出现的依赖冲突、多项目GHC版本不兼容、跨环境构建结果不可复现的问题。它的核心运行逻辑可以总结为三点:
- 每个独立项目绑定固定的GHC版本,以及一套经过兼容性验证的依赖包版本集合(即Stackage维护的LTS快照)
- 所有依赖、对应版本的GHC默认安装在Stack专属的全局缓存目录,不会污染手动安装的全局Cabal/GHC环境
- 所有项目内的构建、运行命令默认在项目绑定的隔离环境中执行,这也是为什么直接输入
ghci调用的是系统全局版本,输入stack exec ghci调用的是当前项目/当前快照绑定的GHCi版本。
不存在“直接用GHC/Cabal的开发方式不再被推荐”的说法,工具选择完全看使用场景。
Stack和Cabal不是替代关系,二者适配不同的使用需求:
- 适合正式团队协作项目、需要跨设备/跨环境复现构建结果的场景:所有协作者共用同一份
stack.yaml锁定快照和依赖版本,不会出现“本地能跑、其他环境跑不通”的问题 - 适合需要频繁切换多版本GHC的场景:无需手动修改全局环境变量,Stack会自动下载对应版本的GHC供指定项目使用
- 部分Haskell工具(如你提到的IHaskell)官方优先提供Stack安装路径,主要是为了规避依赖冲突导致的安装失败
- 如果只是写单文件脚本、临时开REPL验证小段代码,直接用全局Cabal+GHCi完全可行,没有强制使用Stack的要求。
Stack支持无项目的临时REPL环境,不需要写完整的项目配置文件:
- 直接执行
stack ghci即可启动REPL,首次运行时会提示选择全局默认的LTS快照,选择和你本地全局GHC大版本匹配的快照即可 - 如果启动REPL时需要加载指定依赖包,直接附加
--package参数即可,比如需要用到text和lens包时,执行以下命令:
stack ghci --package text --package lens
Stack会自动从对应快照下载需要的包到缓存,启动后的REPL可以直接导入这些包使用,不需要创建专门的项目目录、编写配置文件。
如果需要频繁使用某几个固定包,可以修改用户目录下.stack/global-project/stack.yaml配置文件,把常用包加入依赖列表,之后启动stack ghci默认就可以直接加载这些包。
Stack默认不读取系统全局GHC和Cabal安装的包,是为了保证环境隔离性,如果需要复用现有全局环境,修改两个配置项即可:
- 打开对应项目(或上述全局global-project目录下)的
stack.yaml文件,找到system-ghc配置项,将值设为true:
system-ghc: true
该配置会让Stack跳过自动下载GHC的步骤,直接调用系统PATH中已安装的GHC,注意本地GHC的大版本需要和当前stack.yaml中配置的resolver(快照)对应的GHC版本一致,否则会抛出版本不匹配错误。
2. 如果需要让Stack识别全局通过cabal install安装的包,额外添加一行配置:
no-global-package-db: false
添加完成后,Stack运行时会读取全局Cabal的包数据库,不需要重复安装已经在全局存在的包。
注意:上述配置会破坏Stack的构建可复现性,若更换设备、或全局包版本发生变动可能导致项目构建失败,仅建议个人轻量使用、安装IHaskell这类工具时开启,正式团队协作项目不建议修改这两个配置。
针对你提到的IHaskell安装场景:配置完上述参数后,直接按官方指引执行安装命令即可,安装完成后内核会自动注册到Jupyter的内核路径中,不需要额外调整路径配置。
内容的提问来源于stack exchange,提问作者Bubaya

