Haskell 是一门函数式编程语言。最近想了解下函数式编程,想学习下试试水。但哪曾想到搭建环境花费了好长时间,现在记录下安装过程,为后来者填坑。这可能是最简单的方式了。
安装 stack
推荐使用 stack 工具来安装 haskell 环境,省时省力。它会自动安装 GHC 到单独的目录,还能安装我们所需要的包。
执行以下命令安装 stack:
curl -sSL https://get.haskellstack.org/ | sh
假若安装成功,stack --version 可查看到版本号。
Version 2.3.1, Git revision de2a7b694f07de7e6cf17f8c92338c16286b2878 (8103 commits) x86_64 hpack-0.33.0
stack 相关命令
基础命令
-
stack new project-name创建新工程。
-
stack setup会自动下载编译器,默认在
~/.stack目录下,如下图所示。比如我安装的ghc版本是8.8.3,目录在~/.stack/programs/x86_64-osx/ghc-8.8.3。
-
stack build编译工程。执行命令后,会看到如下日志。为了方便查看,我将日志用空行隔开了。
demo1> configure (lib + exe) Configuring demo1-0.1.0.0... demo1> build (lib + exe) Preprocessing library for demo1-0.1.0.0.. Building library for demo1-0.1.0.0.. [2 of 2] Compiling Lib Preprocessing executable 'demo1-exe' for demo1-0.1.0.0.. Building executable 'demo1-exe' for demo1-0.1.0.0.. [2 of 2] Compiling Main Linking .stack-work/dist/x86_64-osx/Cabal-3.0.1.0/build/demo1-exe/demo1-exe ... demo1> copy/register Installing library in /Users/liusilan/Documents/workspace/my/haskell/demo1/.stack-work/install/x86_64-osx/914b9a9a241328120895004f416724292e0c1440b907fe13776156c85b4acd23/8.8.3/lib/x86_64-osx-ghc-8.8.3/demo1-0.1.0.0-AM0RJfS73DT2gtF91cLy6f Installing executable demo1-exe in /Users/liusilan/Documents/workspace/my/haskell/demo1/.stack-work/install/x86_64-osx/914b9a9a241328120895004f416724292e0c1440b907fe13776156c85b4acd23/8.8.3/bin Registering library for demo1-0.1.0.0.. -
stack exec xx-exe执行命令。
在
stack build中日志的最后一行Installing executable demo1-exe in ...,后面跟的就是exe的路径。按下面的方式执行即可。
stack exec /Users/liusilan/Documents/workspace/my/haskell/demo1/.stack-work/install/x86_64-osx/914b9a9a241328120895004f416724292e0c1440b907fe13776156c85b4acd23/8.8.3/bin/demo1-exe
辅助命令
-
stack path查看
stack相关路径。 -
stack ghc -- --version查看
ghc版本。 -
stack --resolver ghc-8.6.5 setup指定安装
ghc的8.6.5版本。 -
stack config set resolver ghc-8.6.5如果安装了多个
ghc版本,则可通过指定resolver来切换ghc版本。
编写代码
现在,haskell 的环境已经搭好,可以开始编码了。
交互式编程
在终端输入 stack ghci 即可进入交互式编程模式,ghci 是 haskell 的解释器。如下图所示:

虽然通过这种方式比较方便,也可以快速看到结果。但这仅限于简单的编码,在学习的初始阶段还能满足需求。如果要想写些复杂的语句,就不太合适了。
编辑器
因此,选择一个自己熟悉且趁手的编辑器还是很重要的,编码速度会大大提升。由于我用 VSCode 比较多,所以选择了它来配置 haskell 的环境。
在编码时,我们当然是希望有一套类似于 IDE 体验比较好的编程环境,比如代码能自动补全、关键字高亮,错误提示等等。不然干巴巴的一个个字符的敲代码,啥辅助提示都没有,那可太痛苦。
好在 VSCode 提供了 Haskell Language Server 插件,它提供了一系列功能,比如:
- 代码高亮
- 自动补全
- 定义跳转
- 文档提示
- 格式化
- ...
但由于 Haskell Language Server 依赖了 haskell-ide-engine,我们也需要安装它。
下面来介绍如何集成。
VSCode 集成 haskell
安装插件 Haskell Language Server
略过。
编译 haskell-ide-engine
首先简单介绍一下 haskell-ide-engine。
它是一个完整实现了 Language Server Protocol 的服务,所以它可以跟任何支持 LSP 的编辑器集成。如果不了解 LSP,可查看我之前写的文章VSCode 使用 LSP 进行 Swift 开发。
实际上,它也支持很多编辑器,比如 Sublime Text、Emacs、Atom 等等。 如果想要了解其提供哪些功能,可点此查看。
这里我们通过编译源码的方式进行安装。
// clone 代码
git clone https://github.com/haskell/haskell-ide-engine --recursive
// 编译源码
cd haskell-ide-engine && ./install.hs hie
在编译的过程中,一直遇到 Connection timed out 的问题,如下所示。
HttpExceptionRequest Request {
host = "raw.githubusercontent.com"
port = 443
secure = True
requestHeaders = []
path = "/commercialhaskell/stack-templates/master/new-template.hsfiles"
queryString = ""
method = "GET"
proxy = Nothing
rawBody = False
redirectCount = 10
responseTimeout = ResponseTimeoutDefault
requestVersion = HTTP/1.1
}
(InternalException (HostCannotConnect "raw.githubusercontent.com" [Network.Socket.connect: <socket: 672>: failed (Connection timed out (WSAETIMEDOUT))]))
注意错误可能不一样,我在家安装时,则是如下错误。但是都是网络连接问题。
HttpExceptionRequest Request {
host = "s3.amazonaws.com"
port = 443
secure = True
requestHeaders = [("Accept-Encoding",""),("User-Agent","Haskell pantry package")]
path = "/hackage.fpcomplete.com/root.json"
queryString = ""
method = "GET"
proxy = Nothing
rawBody = False
redirectCount = 10
responseTimeout = ResponseTimeoutDefault
requestVersion = HTTP/1.1
}
(InternalException (HandshakeFailed (Error_Misc "Network.Socket.recvBuf: resource vanished (Connection reset by peer)")))
后来换了清华大学镜像,重试了几次,就编译成功了。
在 ~/.stack/config.yaml 中添加如下镜像(建议每次参考清华大学镜像里提及的方式,因为它有可能会更新。)。
但此写法要求 stack >= 2.1.1,如果是其他版本,请参考原链接提供的方式。
package-indices:
- download-prefix: http://mirrors.tuna.tsinghua.edu.cn/hackage/
hackage-security:
keyids:
- 0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d
- 1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42
- 280b10153a522681163658cb49f632cde3f38d768b736ddbc901d99a1a772833
- 2a96b1889dc221c17296fcc2bb34b908ca9734376f0f361660200935916ef201
- 2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3
- 51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921
- 772e9f4c7db33d251d5c6e357199c819e569d130857dc225549b40845ff0890d
- aa315286e6ad281ad61182235533c41e806e5a787e0b6d1e7eef3f09d137d2e9
- fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0
key-threshold: 3 # number of keys required
# ignore expiration date, see https://github.com/commercialhaskell/stack/pull/4614
ignore-expiry: no
注意:这整个就是 config.yaml 的所有内容。这里我也遇到一些问题,添加后 yaml 格式不正确。
如果是跟我一样的新手,打开
config.yaml应该会看到template之类的东西,建议全部删掉,贴上以上内容即可。
如果编译过程中途出现再次出现 Connection time out 问题,建议重试命令。我也是重试 2~3 次后,最后成功了。
当出现如下界面,则说明编译完成。

默认安装路径在 ~/.local/bin 下。为了方便使用命令,可将 ~/.local/bin 加入到 PATH 变量。现在,我们到 ~/.local/bin 目录下看看,可发现有了 hie 相关内容。

在 VSCode 中配置 hie 路径

此时,VSCode 与 haskell 集成的环境已经安装完成。
体验环境
重启下 VSCode,打开之前创建的工程。
注意:新建工程/编译工程/执行可执行文件,还是需要通过
stack相关命令。
如果你看到以下提到的几个功能,那么 hie 则生效了。
-
当鼠标
hover到某个关键字时,会有文档说明,如下所示:
-
当输入字符时,会有自动补全,如下所示:

-
当出现问题时,会提示错误,如下所示:

题外话
看了上述的安装过程一点也不复杂,对吧。但过程中还是踩了不少坑。
其实一开始,我先找到了 这篇文章 作为参考。文章是 2019 年的,经过实践后,看来已经不太适用了。
按照文中的做法,需要安装一些其他的插件,比如 Haskell Syntax Highlighting、Haskell ghc-mod 、haskell-linter、Haskelly。而在安装这些插件依赖的过程中各种报错,烦不胜烦。可能是由于插件没人维护,依赖的 ghc 版本比较低。
后来索性不弄了,另寻他法。最终参照 如何使用 VS Code 開發 Haskell ,只安装 Haskell Language Server 插件,一切都简单了,并且也有以上插件的功能。
另外,Haskell 在 macOS 下的环境搭建 这篇文章还提到了使用 IntelliJ IDEA 来运行 haskell 项目。不过我没有试验成功,有兴趣的可以尝试一下。
参考文章: