慢慢学Haskell(一):Hello Haskell

2,317 阅读4分钟

初衷

今年8月我又一次开启了学习Haskell的的旅程。为什么说是又呢?因为两年前我经历过一次学习Haskell从入门到放弃的过程。这次重新开始学习Haskell,原因有三。

  • 其一,我所从事的前端开发领域函数式编程思想的应用越来越普遍,我能从日常开发中感受到函数式编程的简洁与优雅,进而产生了兴趣。
  • 其二,当我翻开《Learn You a Haskell for Great Good》这本书,作者在开篇写到自己也是学了两遍才掌握Haskell,这让我觉得自己两年前被劝退没有什么。
  • 其三,我希望自己能够通过学习一门小众而有特点的语言让自己得到成长。

在学习的过程中,我发现Haskell中概念很多,需要认真的理解和梳理。而中文世界中Haskel的相关资料有限且陈旧。所以在此做一些记录,一来强化自己的记忆和理解,同时也期望能够帮助到后来学习Haskell的同学。

我的学习路径

主要参照parker liu大佬在知乎上如何学习函数式编程?中的回答

  • 从《Learn You a Haskell for Great Good》《Haskell函数式编程入门》入手学习
  • 通过codewar提升语言熟练度
  • 学习《Real World Haskell》
  • 学习《Structure and Interpretation of Computer Programs》
  • ...

环境配置

多少英雄汉,倒在难把环境安

Haskell相关的工具主要有以下四个:

  • GHC:the Glasgow Haskell Compiler,Haskell的编译器
  • cabal-install:包管理工具,类似于js世界的npm
  • stack :跨平台的项目管理工具,集成了GHC多版本管理,包依赖管理,项目打包,测试等相关功能。和cabal-install有部分功能重合。
  • haskell-language-server(HLS):Haskell官方的LSP实现,VS Code中Haskell插件的语法提示,代码审查等辅助功能都是基于HLS实现。

对于Linux,OSX环境,官方推荐使用 GHCup 工具安装上述工具,终端中输入以下命令即可一键安装。

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

安装过程中可能会因为github被墙的缘故,导致部分内容安装失败。个人建议通过配置github https proxy的方式来解决。GHCup这个工具非常优秀,通过它我们可以很方便的安装,切换,删除不同版本的GHC,stack,cabal-install以及HLS,这个工具甚至还贴心的提供了终端内的图形化界面来方便用户操作。要开启这个图形化界面,我们需要在终端中输入以下命令:

ghcup tui

tui.png

初学Haskell的时候一般只会用到GHC。终端内输入ghci我们就可以愉快的玩耍了。

ghci.png

关于编辑器的选择,我个人使用VS Code,安装Haskell的官方插件即可获得不错的开发体验。

haskell plugin.png

Hello World

失败是成功之母,Hello world 是代码之母

对于Haskell,我们可以直接在ghci中输入print "hello world"来实现

hello_world.png

我们也可创建一个helloworld.hs文件,输入以下内容

hello :: IO ()
hello = print "hello world"

ghci中通过:l加载helloworld.hs并执行hello函数

hello_world_hs.png

轻轻松松Hello World搞定,然而从Hello World到写出靠谱代码的过程基本上如下图所示:

Draw a horse.jpeg

所以我们还是慢慢来。先看下Haskell官网上关于素数的示例:

primes = filterPrime [2..]
  where filterPrime (p:xs) =
          p : filterPrime [x | x <- xs, x `mod` p /= 0]

只需要三行代码我们就得到了一个从2开始长度无限的素数列表,让我们执行一下看看效果:

primes.png

  • primes表示由从2开始的所有素数组成的list
  • take 10 primes表示获取这个素数列表的前十项,因而我们得到了[2,3,5,7,11,13,17,19,23,29]
  • primes !! 10表示获取素数列表中index为10的元素,我们得到了31

要读懂这段代码,我们需要了解以下概念:

  • 惰性求值
  • List Comprehension
  • Range,通过[2...]表示大于等于2的正整数列表,因为Haskell惰性求值的特点,列表的长度可以是无限的。
  • Where 关键字
  • ...

这些内容我会在下一篇文章中做一下介绍,大家如果感兴趣的话也可以阅读Learn You a Haskell for Great Good中的第二章节。

Haskell 小百科

Haskell的命名源自美国数学家Haskell Brooks Curry,用于纪念他在λ验算和组合逻辑方面作出的突出贡献。同时柯里化的概念也以他的名字命名。

LSP是Language Server Protocol的缩写,并不是你们想到的那个东东(手动狗头

TO BE CONTINUED.png