Haskell 简明教程
编写 Haskell 需要一个编译器和一个交互式环境。目前事实上的标准实现是 GHC (Glasgow Haskell Compiler)。
官方推荐的安装工具是 GHCup,它可以在 Linux、macOS 以及 Windows (WSL / PowerShell) 上统一管理 GHC、构建工具 Cabal、Stack 和语言服务器 HLS(Haskell Language Server)。
在类 Unix(Linux / macOS)终端中执行:
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
按照屏幕提示即可完成 GHC、Cabal、Stack 与 HLS 的安装及环境变量配置。
若使用 Arch Linux:
sudo pacman -S ghc cabal-install
若使用 Ubuntu / Debian:
sudo apt update
sudo apt install ghc cabal-install
若使用 macOS(Homebrew):
brew install ghc cabal-install
安装完成后,在终端验证工具链版本:
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.10.x
$ cabal --version
cabal-install version 3.12.x
GHC 自带一个交互式环境(REPL),名为 GHCi。在终端中输入 ghci 即可启动:
$ ghci
GHCi, version 9.10.3: https://www.haskell.org/ghc/ :? for help
ghci>
可以直接把 GHCi 当作计算器或试验场:
ghci> 2 + 3 * 4
14
ghci> putStrLn "Hello, Haskell!"
Hello, Haskell!
GHCi 提供了一系列以冒号 : 开头的内置命令:
退出::quit 或简写 :q(在 Linux/macOS 下也可以直接按 Ctrl + D)。
查询类型::type 或简写 :t,打印表达式或函数的类型签名。
ghci> :t "Hello"
"Hello" :: [Char]
ghci> :t (+)
(+) :: Num a => a -> a -> a
查询详细定义::info 或简写 :i,查看某个类型、函数或类型类的声明、定义所在源码位置以及实现的实例列表。
查询类型阶数(Kind)::kind 或简写 :k,查看类型构造器的形态(例如 :k Maybe 返回 * -> *)。
加载与重载文件:
:load <文件名> 或简写 :l <文件名>:加载当前目录下的源文件。
:reload 或简写 :r:重新编译并载入最后一次修改的文件。
模块浏览::browse <模块名> 查看指定模块导出的所有函数与类型列表。
查看文档::doc <标识符> (较新版本的 GHC 支持),在终端直接阅读指定函数或类型的 Haddock 文档。
查看内置帮助::? 列出所有内置命令。
这两项设置对学习和调试很有帮助:
ghci> :set +t
ghci> 10 + 20
30
it :: Num a => a
ghci> :set +s
ghci> sum [1..1000000]
500000500000
it :: (Num a, Enum a) => a
(0.04 secs, 80,064,288 bytes)
:set +t 会在每次求值后自动输出结果的类型;:set +s 会输出执行耗时与内存分配量。
无需修改文件,可在 GHCi 中动态启用 GHC 语言扩展:
ghci> :set -XOverloadedStrings
ghci> :set -XBinaryLiterals
ghci> 0b101010
42
在 REPL 中定义包含较多分支的函数或代数数据类型时,单行输入很不方便。使用 :{ 与 :} 可进入多行编辑模式:
ghci> :{
ghci| data Shape
ghci| = Circle Double
ghci| | Rectangle Double Double
ghci| deriving (Show)
ghci| :}
ghci> Circle 3.14
Circle 3.14
在用户主目录下的 ~/.ghci 文件中可以写入常用的启动配置,避免每次手动设置:
:set prompt "\ESC[34mλ> \ESC[m"
:set +t
:set -XOverloadedStrings
除了在 GHCi 中交互试运行,日常开发还常使用脚本化执行与编译:
对于小脚本或一次性任务,无需生成编译产物:
新建 Script.hs:
module Main where
main :: IO ()
main = putStrLn "Running Haskell script directly."
使用 runghc 运行:
$ runghc Script.hs
Running Haskell script directly.
新建源文件 Main.hs:
module Main where
main :: IO ()
main = putStrLn "Hello, World from compiled Haskell."
使用 ghc 编译:
$ ghc -O2 Main.hs -o myprogram
编译完成后会生成目标文件 .o、接口文件 .hi 以及可执行文件 myprogram。参数 -O2 开启较高级别的优化。
执行程序:
$ ./myprogram
Hello, World from compiled Haskell.
Haskell 的第三方包都发布在 Hackage 上,每个包的页面里有由 Haddock 生成的 API 文档,标准库 base 也在其中。
Hoogle 是 Haskell 特有的搜索引擎,除了按名字搜索,还可以按类型签名搜索。例如不记得”把函数作用到列表每个元素”的函数叫什么,可以直接搜类型:
(a -> b) -> [a] -> [b]
结果会列出 map 以及其他签名匹配或相近的函数。这在学习阶段很有用:先想清楚需要的类型,再去查有没有现成的函数。
GHCi 里的 :doc 和 :info 可以在不离开终端的情况下查看已加载模块的文档和定义。
GHC 是 Haskell 的主流编译器,GHCi 是它附带的交互式环境。
:t、:i、:k 与 :doc 可以在 GHCi 里直接查看类型、定义、Kind 和文档。
:set +t 与 :set +s 分别显示求值结果的类型和耗时。
独立程序的入口是 Main 模块下的 main :: IO (),可以用 runghc 直接运行,或用 ghc 编译成可执行文件。