本文介绍如何在类 UNIX 系统上(Linux、MacOS、FreeBSD)从零开始一步步安装 Haskell 工具链(编译器、构建工具、编辑器),特别是考虑到国内特殊网络环境,会介绍如何使用国内源。注意:
在 2023 年的今天,Cabal 已经取得了长足进步,因此本文将完全不涉及 Stack。
如果你使用 Windows,好消息是 Haskell 工具链完整支持 Windows,但超出本文范围之外。尽管如此,本文仍然适用于 WSL。
目前国内只有上海交大和中科大有 Haskell 工具链的完整镜像(GHCup、Hackage、Stackage)。本文采用中科大镜像,你可以手动修改命令来使用其他镜像。
本文的目标读者是对 Haskell 没有任何了解的初学者。
GHCup 是一个 Haskell 工具链的版本管理器。简单来说,它可用于安装不同版本的 GHC、Cabal、HLS 等工具。
GHCup 是一个近期出现的工具,因此国内目前只有中科大和上海交大有镜像。在安装 GHCup 之前,我们要做一件额外的工作,创建 ~/.cabal
目录,并创建 ~/.cabal/config
文件,填入如下内容:
repository mirrors.ustc.edu.cn
url: https://mirrors.ustc.edu.cn/hackage/
secure: True
这是因为 GHCup 在安装 Cabal 时会进行初始化(会下载一个 100MB 的文件),但此时我们还没有替换 Hackage 源!这一步首先替换 Hackage 源。之后安装过程就会如丝般顺滑。
在终端中运行如下命令:
curl --proto '=https' --tlsv1.2 -sSf https://mirrors.ustc.edu.cn/ghcup/sh/bootstrap-haskell | BOOTSTRAP_HASKELL_YAML=https://mirrors.ustc.edu.cn/ghcup/ghcup-metadata/ghcup-0.0.7.yaml sh
(是的,一行。)
很快,你会看到如下界面:
**安装过程请仔细阅读所有提示。**针对三个问题,下面是我的推荐:
**是否将 ghcup 目录加入 PATH?**直接回车接受默认值,如果你在看这篇文章,说明你一定会用到。
**是否安装 Haskell Language Server?**安装与否均可,之后想装也很容易。这里输入 Y 安装(你大概是希望使用更高级的 IDE 功能的)。
**是否安装 Stack?**输入 N,不安装。
之后一路回车,GHCup 将下载安装推荐版本的 GHC 和 Cabal,并完成初始化。(截至本文写作时,GHC 版本是 8.10.7)。结束后,你会看到一大片提示,请仔细阅读所有输出。这里必做的事情是设置当前 shell 的 PATH
(或者重启一下 shell 也行):
source ~/.ghcup/env
搞定!你已经可以用起来 Haskell 了。
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.10.7
$ cabal --version
cabal-install version 3.6.2.0
compiled using version 3.6.2.0 of the Cabal library
$ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/ :? for help
Prelude> putStrLn "Hello, Haskell!"
Hello, Haskell!
Prelude>
Leaving GHCi.
我们上面用了环境变量临时修改了 GHCup 元数据地址,这里我们把镜像写到配置里让国内源永久生效。修改 ~/.ghcup/config.yaml(如不存在就创建),添加如下内容:
url-source:
OwnSource: https://mirrors.ustc.edu.cn/ghcup/ghcup-metadata/ghcup-0.0.7.yaml
ghcup
有一个很好用的命令叫 tui
,所有 ghcup 的操作均可以从这里完成,运行 ghcup tui
会显示如下界面。
其中打双对勾的是当前选中版本。比如你安装了 GHC 9.2.1 和 GHC 8.10.7 两个版本,但是目前选中的是 8.10.7,那么运行 ghc 命令会调用 8.10.7 版本而非 9.2.1 版本。你可以安装多个版本,但一次只能选中一个版本(用 s
键选中别的版本)。好了,剩下的命令都顾名思义,自己试试即可。
如果想安装 HLS 的话,随时可以从这里安装。
本文的重点不是配置编辑器,下面只给出一些提示。请参阅其他资料(尤其是相应插件自己的文档)了解如何配置、如何使用。
Visual Studio Code 是目前最流行的代码编辑器之一,Haskell 语言服务器则为 LSP 提供了较好的支持,两者相得益彰。只需在扩展市场中搜索名为 Haskell 的扩展并安装即可。
之后,任意打开一个 .hs 文件,Visual Studio Code 就会自动调用 GHCup 已经安装的 HLS,可以充分体验 Haskell 的 IDE 编辑体验了!(如果 VSCode 提示你要下载 HLS,请下转故障排除章节。)
恭喜,至此你已经完成配置了 2023 年最先进的 Haskell 工具链+编辑环境!尽情享受吧!
Emacs 默认没有 Haskell 代码高亮,但可以安装 haskell-mode。它的功能非常丰富,推荐阅读其文档。比如一个很有用的命令是 haskell-process-load-or-reload
,可以用来快速打开一个 ghci 并载入当前文件。
如果想要使用 HLS:
先手动通过 ghcup 安装 HLS。
再安装 lsp-mode、lsp-haskell。
That’s all!
vim 原生支持 Haskell 的代码高亮。要与 HLS 集成,可使用 coc.nvim。
使用 Haskell 时,强烈建议首先创建一个项目。这是因为 Cabal 让使用第三方库非常方便。Cabal 有一个不错的使用指南,值得收藏:
$ mkdir my-first-haskell-project
$ cd my-first-haskell-project
$ cabal init # 在当前目录下初始化一个 Cabal 项目
Guessing dependencies...
Generating LICENSE...
Warning: unknown license type, you must put a copy in LICENSE yourself.
Generating CHANGELOG.md...
Generating app/Main.hs...
Generating my-first-haskell-project.cabal...
Warning: no synopsis given. You should edit the .cabal file and add one.
You may want to edit the .cabal file and add a Description field.
$ tree .
.
├── CHANGELOG.md
├── app
│ └── Main.hs
└── my-first-haskell-project.cabal
1 directory, 3 files
可以看到,Cabal 创建了 3 个文件。其中 CHANGELOG.md 是用来记录版本更新内容的,对初学者来说不用关心。
打开 .cabal 文件,除去基本的项目信息外,有一个 executable
段落:
executable my-first-haskell-project
main-is: Main.hs -- 入口文件名
build-depends: base ^>=4.14.3.0 -- 依赖
hs-source-dirs: app -- 代码目录
default-language: Haskell2010 -- 默认语言
其中, ^>=
对 base
(Haskell 标准库) 的版本增加了限制。对学习者来说,可以忽视这些限制(直接去掉版本限制)。下面我们增加 time 这个库为一个依赖:
executable my-first-haskell-project
main-is: Main.hs
build-depends: base, time -- 这里添加了 time 库
hs-source-dirs: app
default-language: Haskell2010
然后,就可以在代码文件 app/Main.hs
中使用了:
module Main where
import Data.Time.LocalTime -- 来自 time 库
main :: IO ()
main = do
now <- getZonedTime
print now
(补充说明:Cabal 在编译时会自动求解一套互相兼容的包的版本,因此不写版本限制对学习者来说最方便,出问题的概率小了很多。但同时要注意这是不好的开发实践,在发布软件时最好先使用 cabal gen-bounds
命令生成兼容的版本范围。尽管不写版本范围让可行解的范围大了不少,但仍然有可能出现不兼容问题——会输出大量令人生畏的报错信息——这多数情况是因为你的某个依赖实在是太旧了,最好换一个新的同类包。)
$ cabal build # 编译
[一大堆输出]
[1 of 1] Compiling Main [一堆输出]
Linking ..../my-first-haskell-project
$ cabal run # 运行
[cabal run 会自动调用 cabal build,所以这里可能是 Up to date 也可能是和 cabal build 一样的一大堆输出]
2022-01-11 01:38:32.87706 CST
$ cabal repl
[一大堆输出]
*Main> # ghci,但自动载入 Main 模块,并且可以自由用任何第三方依赖里的模块
Cabal 在编译时会自动从 Hackage 上下载并构建第三方依赖。因此你可以自由地在 Hackage 上找自己感兴趣的包,然后加到项目依赖里来实验。比如下面这些好玩的包,可以试试看!
gloss, 2D 图形库。
reanimate, 类似 manim 的动画库。首页有很多酷炫例子。
gi-gtk-declarative, GUI 库。
inline-r, 与 R 语言无缝协作。
Chart, 绘制 2D 图表。
accelerate, 硬件加速的数组运算库,可以编译到 GPU 上运行!
ad, 自动微分。
等等等等……
Hackage 上有很多有趣的包,现在都是你的了。
rm -rf ~/.cabal ~/.ghcup ~/.ghc
有如下原因:
你没有使用 GHCup 安装 HLS。现在去安装一下?如果还不行,再看下面的。
你没有添加 GHCup 的路径到 PATH 中。如果始终不行,参考下面的配置。
在 Haskell 扩展页面,点击页面上的小齿轮打开扩展配置。
找到 “Haskell: Server Executable Path” 配置项。
输入 ~/.ghcup/bin/haskell-language-server-wrapper
。
重启 VSCode。
这时候重新打开文件应该就可以正确调用到 GHCup 安装的 HLS 上了。
最可能的原因是你启用了 HLS 目前不支持的新版本 GHC。如果想使用 HLS,请务必在 ghcup tui
中选中一个有 hls-powered 标记的 GHC 版本(比如 9.0.1, 8.10.7 等)。
Mac 上安装时,若报错信息中有 configure
字样,是因为没有安装 Xcode Command Line Tools。
如果步骤“执行安装”中运行命令后提示类似 curl: command not found
,需要安装curl。Linux 下命令为:sudo apt install curl
。
在 Linux 下可能需要额外安装一些包。以 Linux Mint 20.3(同 Ubuntu 20.04)为例:执行sudo apt install build-essential libgmp-dev libncurses5-dev libncursesw5-dev
来安装 gcc、gmp 库、ncurses 库。其他发行版可参照之。
修订记录
2023-07-09: 少量格式和字句修正;「2022」更新到「2023」。
2022-09-15: 将 ghcup metadata 版本升级至 0.0.7。