2023: A Haskell Odyssey
“Don’t try to understand it. Feel it.” – Tenet
Start: Learn You a Haskell for Great Good!
Haskell的语法是优雅的。
诸如“允许符号字符串作为name”、“可以用中缀形式定义并应用函数”、“内置的$
, .
运算符”等设计,为程序员写出更易读的代码风格创造可能。
这使得Haskell克服了同为函数式的Lisp括号满天飞的问题(这里有一个笑话。当然我也知道这是Lisp的Parser实现简单的原因),
也克服了C系语法对较为死板的apply方式。
因为有学过Scheme,平时在写Python和Java的时候也经常使用一些函数式的写法(Stream也是函数式(振声)),所以用函数式思维写程序并没有什么障碍。 但是Haskell的库不太熟,所以还是经常做出手搓复杂轮子的事情。还是有待精进啊!
Haskell让我耳目一新的,
一,是与我比较熟悉的Java截然不同的类型系统,这也是我接下来学习的对象之一;
二,也是学习Haskell时最“臭名昭著”的难点,是以Monad
为代表的类,也就是带computing environment/context的类。
似乎这也被认为是函数式编程的进阶内容(这不是我说的,参考该课程安排)。
这与我印象中其他语言的进阶内容不相符:难道不应该是一些和语法相关的写法吗?(虽然对库的使用也是很重要的)
顺着上面所说,也有人称Haskell为“Value-Oriented Programming”,也许是因为Haskell强大的表达能力并非源于某些语法,而是由数据结构来进行复杂表达?感觉有点Meta Programming的味道了。然后我就突然想起来之前看过的一个知乎回答提到Monad
和Aspect-Oriented Programming的关系。
自由的表达能力加上出神入化的数据结构以实现一些神奇的功能,或许这就是Haskell哲学吧!
上面瞎扯了这么多不通顺的东西,看起来挺没意思的。接下来就顺着Learn you a Haskell的章节顺序来做一点小小的我觉得有意思的地方吧!
Introduction (Installation)
一些比较入门的东西,我觉得比较抽象的一点在安装GHCup
自带的包管理器Cabal
上。
不知道是不是得益于国内的网络质量,wsl2
用官网的安装脚本安装的时候会卡在Cabal
的一步复制某个default configuration上。
我目前的workaround是:
- 在这一步
Ctrl-c
掉; - 然后手动运行
cabal user-config update
去产生一个默认config; - 选择你喜欢的
hackage
源,加入~/.cabal/config
里,替换掉原来的官方仓库(你最喜欢的源一定是NJU Mirror,对吧?)。
(我在写这一节,查看NJU Mirror对应手册的时候才发现手册说得已经很清楚了。向当时断断续续安装几个晚上而不得的我致以崇高敬意)。
这样的话似乎也能正常使用,我后来用Cabal
在本地安装了hoogle
,一个很酷的API查询插件。
另外就是在安装的时候建议安装hls
(Haskell Language Server),这样的话用VSCode
时才能使用自动补全和语法检查建议等功能。配置VScode的ghcup
路径的时候注意和别的工具不太一样,不是到bin文件夹,而是直接配置到ghcup
,比如~/.ghcup/bin/ghcup
。
Starting-Out
我想你注意到了ghci
,并且很容易把它理解成类似Python Intepreter一样的东西。
但是此二者有着一定差别:在学习,你可以完全基于Python Intepreter进行所有实验与测试,但ghci
做不到这一点,部分语法无法可读地在ghci
内表达,此外在语义上也有部分区别。
学到IO
和Monad
相关章节以后你可能会有更深刻的体会。
因此,我建议你仿照作者在Introduction
一节最后描述,在Baby's first functions
一节开头再次演示的工作流,即在某个Haskell源文件里编写代码,然后在ghci
内用:l
命令将代码load进ghci内的方式,进行测试。