我将根据您在 Haskell 中的技能水平来订购本指南,从绝对的初学者到专家。请注意,这个过程将花费数月(数年?),因此相当长。
绝对的新人
首先,Haskell 具备足够的技能,可以做任何事。它速度非常快(根据我的经验,仅落后于 C 和 C++),并且可用于从模拟到服务器、GUI 和 Web 应用程序的任何内容。
然而,对于 Haskell 初学者来说,有些问题比其他问题更容易编写。数学问题和列表处理程序是很好的选择,因为它们只需要最基本的 Haskell 知识就可以编写。
学习 Haskell 基础知识的一些很好的指南是快乐学习Haskell教程 http://www.happylearnhaskelltutorial.com以及前 6 章为你学习 Haskell 以获得伟大的好处 http://learnyouahaskell.com/(或其JupyterLab 适配 https://github.com/jamesdbrock/learn-you-a-haskell-notebook)。在阅读这些内容时,最好也用您所知道的知识来解决简单的问题。
另外两个好资源是Haskell 编程从第一原理开始 http://haskellbook.com/, and Haskell 编程 http://www.cs.nott.ac.uk/%7Epszgmh/pih.html。它们每章都配有练习,因此您会遇到与您在最后几页学到的内容相匹配的小简单问题。
一个很好的尝试问题列表是Haskell 99 问题页面 https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems。这些一开始非常基础,随着你的继续,会变得越来越困难。做很多这样的事情是非常好的练习,因为它们可以让你练习递归和高阶函数的技能。我建议跳过任何需要随机性的问题,因为这在 Haskell 中有点困难。查看这个问题 https://stackoverflow.com/questions/5683911/simple-haskell-unit-testing如果您想使用 QuickCheck 测试您的解决方案(请参阅中间的 below).
一旦你完成了其中的一些,你就可以继续做一些欧拉计划 http://projecteuler.net/index.php?section=problems问题。这些是按照完成人数排序的,这很好地表明了难度。这些问题比前面的问题更考验你的逻辑和 Haskell,但你仍然应该能够完成前几个问题。 Haskell 解决这些问题的一大优势是整数的大小不受限制。为了解决其中一些问题,阅读《学习 Haskell》的第 7 章和第 8 章也会很有用。
Beginner
之后,您应该对递归和高阶函数有相当好的掌握,因此这是开始解决一些更现实世界问题的好时机。一个很好的起点是现实世界哈斯克尔 http://book.realworldhaskell.org/(在线书籍,您也可以购买纸质版)。我发现对于以前从未做过函数式编程/使用过递归的人来说,前几章介绍得太多太快了。然而,通过前面的问题的练习,你应该会发现它完全可以理解。
解决书中的问题是学习如何在 Haskell 中管理抽象和构建可重用组件的好方法。这对于习惯面向对象(oo)编程的人来说至关重要,因为正常的 oo 抽象方法(oo 类)不会出现在 Haskell 中(Haskell 有类型类,但它们与 oo 类有很大不同,更像 oo 接口)。我认为跳过章节不是一个好主意,因为每一章都引入了很多新的想法,这些想法将在后面的章节中使用。
过了一会儿,您将到达第 14 章,即可怕的 monads 章节 (dum dum dummmm)。几乎每个学习 Haskell 的人都很难理解 monad,因为这个概念非常抽象。我想不出另一种语言中有任何概念像函数式编程中的 monad 一样抽象。 Monads 允许将许多想法(例如 IO 操作、可能失败的计算、解析……)统一到一个想法下。因此,如果在阅读 monad 章节后您还没有真正理解它们,请不要感到沮丧。我发现阅读对单子的许多不同解释很有用;每个人都对问题提出了新的视角。这里有一个非常好的Monad 教程列表 https://wiki.haskell.org/Tutorials#Using_monads。我强烈推荐关于 Monad 的一切 https://wiki.haskell.org/All_About_Monads,不过其他的也都不错。
此外,这些概念需要一段时间才能真正被理解。这是通过使用来实现的,但也通过时间来实现。我发现有时候解决问题比睡觉更有帮助!最终,这个想法会被采纳,你会想知道为什么你很难理解一个实际上非常简单的概念。当这种情况发生时真是太棒了,当它发生时,你可能会发现 Haskell 成为你最喜欢的命令式编程语言:)
为了确保您完全理解 Haskell 类型系统,您应该尝试解决20 个中级 Haskell 练习 http://blog.tmorris.net/posts/20-intermediate-haskell-exercises/。这些练习使用有趣的函数名称,如“furry”和“banana”,可以帮助您很好地理解一些基本的函数式编程概念(如果您还没有这些概念)。与一堆贴满箭头、独角兽、香肠和毛茸茸的香蕉的文件一起度过一个美好的夜晚。
中间的
一旦你理解了 Monads,我认为你已经从初级 Haskell 程序员过渡到中级 Haskell 了。那么接下来该去哪里呢?我首先推荐的(如果您还没有通过学习 monad 来学习它们)是各种类型的 monad,例如 Reader、Writer 和 State。再次,Real world Haskell 和 All about monads 对此进行了很好的报道。要完成 monad 培训,必须学习 monad 转换器。这些使您可以将不同类型的 Monad(例如 Reader 和 State monad)组合为一。一开始这似乎没什么用,但使用一段时间后,你会想知道没有它们你是如何生活的。
现在,如果您愿意,您可以完成现实世界的 Haskell 书。现在跳过章节并不重要,只要你掌握了单子。只需选择您感兴趣的内容即可。
凭借您现在掌握的知识,您应该能够使用 cabal 上的大多数软件包(至少是有文档记录的软件包......),以及 Haskell 附带的大多数库。值得尝试的有趣库列表如下:
-
Parsec https://wiki.haskell.org/Parsec:用于解析程序和文本。比使用正则表达式好得多。优秀的文档,还有现实世界的 Haskell 章节。
-
快速检查 http://www.cse.chalmers.se/%7Erjmh/QuickCheck/:一个非常酷的测试程序。你所做的就是编写一个应该始终为真的谓词(例如length (reverse lst) == length lst
)。然后,您将谓词传递给 QuickCheck,它将生成许多随机值(在本例中为列表)并测试谓词对于所有结果是否都为真。另请参阅在线手册 http://www.cse.chalmers.se/%7Erjmh/QuickCheck/manual.html.
-
HUnit http://hunit.sourceforge.net/:Haskell 中的单元测试。
-
gtk2hs http://projects.haskell.org/gtk2hs/:Haskell 最流行的 GUI 框架,可让您编写 gtk 应用程序。
-
快乐栈 http://happstack.com/:Haskell 的 Web 开发框架。不使用数据库,而是使用数据类型存储。非常好的文档(其他流行的框架是snap http://snapframework.com/ and yesod http://www.yesodweb.com/).
此外,还有许多您最终应该学习的概念(例如 Monad 概念)。这比第一次学习 Monad 更容易,因为你的大脑将习惯于处理所涉及的抽象级别。学习这些高级概念以及它们如何组合在一起的一个很好的概述是类型分类百科全书 http://www.haskell.org/haskellwiki/Typeclassopedia.
-
Applicative:类似于 Monad 的接口,但功能较弱。每个 Monad 都是适用的,但反之则不然。这很有用,因为有些类型是 Applicative 但不是 Monad。此外,使用 Applicative 函数编写的代码通常比使用 Monad 函数编写等效代码更具可组合性。看函子、应用函子和幺半群 http://learnyouahaskell.com/functors-applicative-functors-and-monoids#functors-redux来自《学习 Haskell 指南》。
-
Foldable http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Foldable.html,可穿越 http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Traversable.html:类型类抽象了列表的许多操作,以便相同的功能可以应用于其他容器类型。另请参阅Haskell 维基解释 https://wiki.haskell.org/Foldable_and_Traversable.
-
Monoid https://wiki.haskell.org/Monoid:Monoid 是一种具有零(或空)值和一个操作的类型,用符号表示<>
将两个幺半群连接在一起,这样x <> mempty = mempty <> x = x
and x <> (y <> z) = (x <> y) <> z
。这些称为恒等律和结合律。许多类型都是幺半群,例如数字,mempty = 0
and <> = +
。这在很多情况下都很有用。
-
Arrows http://www.haskell.org/arrows/:箭头是一种表示接受输入并返回输出的计算的方式。函数是最基本的箭头类型,但还有许多其他类型。该库还有许多非常有用的操作箭头的函数 - 即使仅与普通的旧 Haskell 函数一起使用,它们也非常有用。
-
Arrays https://wiki.haskell.org/Modern_array_libraries:Haskell 中的各种可变/不可变数组。
-
ST Monad https://wiki.haskell.org/Monad/ST:让您可以编写运行速度非常快的可变状态代码,同时在 monad 之外仍然保持纯净。请参阅链接查看更多细节。
-
FRP:函数响应式编程,一种新的、实验性的编写处理事件、触发器、输入和输出(例如 GUI)的代码的方法。不过我对此了解不多。Paul Hudak 谈论 yampa http://vimeo.com/96744621是一个好的开始。
您应该了解许多新的语言功能。我只是列出它们,你可以从谷歌找到很多关于它们的信息,哈斯克尔维基百科 http://en.wikibooks.org/wiki/Haskell、haskellwiki.org 网站和GHC 文档 https://wiki.haskell.org/GHC.
- 多参数类型类/函数依赖
- 类型家族
- 存在量化类型
- 幻影类型
- GADTS
- 其他的...
Haskell 的很多内容都是基于范畴论 http://en.wikipedia.org/wiki/Category_theory,所以你可能想研究一下。一个好的起点是计算机科学家范畴论 https://rads.stackoverflow.com/amzn/click/com/0262660717。如果你不想买这本书,作者的相关也很优秀。
最后,您将想要了解有关各种 Haskell 工具的更多信息。这些包括:
-
ghc https://wiki.haskell.org/GHC(及其所有功能)
-
cabal http://www.haskell.org/cabal/:Haskell 包系统
-
darcs http://darcs.net/:用 Haskell 编写的分布式版本控制系统,在 Haskell 程序中非常流行。
-
haddock http://www.haskell.org/haddock/:Haskell 自动文档生成器
在学习所有这些新库和概念的同时,用 Haskell 编写一个中等规模的项目非常有用。它可以是任何东西(例如小游戏、数据分析器、网站、compiler http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours)。致力于此将使您能够应用您现在正在学习的许多内容。你会在这个水平上停留很长时间(这就是我所处的位置)。
Expert
你需要几年的时间才能到达这个阶段(2009 年你好!),但从这里我猜你开始撰写博士论文、新的 ghc 扩展,并提出新的抽象。
寻求帮助
最后,在任何学习阶段,都有多个地方可以获取信息。这些都是:
- #haskell irc 频道
- the 邮件列表 https://wiki.haskell.org/Mailing_lists。这些内容值得注册,只是为了阅读其中的讨论 - 有些非常有趣。
- haskell.org 主页上列出的其他地点
结论
好吧,结果比我预期的要长……无论如何,我认为精通 Haskell 是一个非常好的主意。这需要很长时间,但这主要是因为你正在通过这样做学习一种全新的思维方式。这不像学Java后学Ruby,而是像学C后学Java。而且,我发现学习Haskell后我的面向对象编程技能得到了提高,因为我看到了许多抽象思想的新方法。