Skip to content

Latest commit

 

History

History
544 lines (300 loc) · 24 KB

guide-zh_CN.md

File metadata and controls

544 lines (300 loc) · 24 KB

前言

这是我推荐的学习Haskell之路。

请切记:别在不懂的地方打转,先继续读下去!

社群

IRC频道是Freenode上的#haskell-beginners

IRC web版用户端可在这里取得

Haskell邮件群组

社群参与原则

请参考Chris Done所撰:Teaching

请友善待人,尖酸苛薄只会把人吓跑、令人不愿再参与而已。

低劣的批评只让你自己痛快,对听者毫无帮助。

别说『这很简单』、『这没什么』。这会让人觉得要花这么多功夫来弄懂是因为自不如人,学得慢的人通常是学得最全面的人,这值得称赞!

当别人承认他不知道的时候,不要故作惊讶。这会让他难过,而你除了表现得好像很行,什么也没得到。

不要说『其实...这样才对...』(well, actually...)。当有人说了什么『几乎正确』的话,而你说些『其实...这样才对』来做些枝微末节的修正,这很恼人,尤其这常常跟整个讨论根本八竿子打不着。我并不是在说人们不在乎精确,只是像这样的发言通常是作秀成分居多,而非为了追寻真实。


以上部分内容来自the Recurse Center手册。感谢他们愿意公开分享!

安装Haskell

通过 Stack 使用 Haskell

获取 Stack 来安装 GHC 构建你的项目。

如果你从未了解过 Stack 并需要它的概述,请看这个comprehensive Stack video tutorial

不要安装 HASKELL PLATFORM

不要遵循 Haskell.org 里面的说明,直接使用 Stack。

为什么不用 platform?

https://mail.haskell.org/pipermail/haskell-community/2015-September/000014.html

主要学习课程

Yorgey's cis194课程

请先通过这门课学习,这是我最推荐入门Haskell的课。

此课程的教材可于线上取得

Brent Yorgey的课是我目前所知最好的。它之所以好,因为 它不只教你些基础知识,还教你parser combinators。

如果你不是个程序设计师,或缺乏经验,那么这门课可能没这么适合。建议你从 Thompson的这本书开始,然后再转到cis194。


FP课程

在你完成上述Yorgey的cis194后,我推荐继续挑战此课程。

这门课发布在github上

透过实现cis194中所介绍过的种种抽象表述,你会有更深入的了解。这样的练习对于 熟悉Haskell中每天都会面对的Functor/Applicative/Monad等等至关重要。 先做cis194,紧接着FP,是这整篇Haskell学习导览的核心,也是我​​教每个人Haskell的方式。


补充课程cs240h

提供更多中阶以上议题的教材

线上教材

这是Bryan O'Sullivan在Stanford所教课程的线上版。 如果你不知道他是谁,去翻翻Haskell的函式库吧!几乎一半以上常用的套件都有他的名字。 特别是phantom types、information flow control、language extensions、concurrency、pipes和lenses。


<- / do / list comprehension简便语法到底是什么?

很棒的解释

了解list和fold

学习常用的typeclasses

对了解FunctorApplicativeMonad、`Monoid`和其他typeclasses很有帮助,而且还有 些针对Haskell的范畴论(category theory)的解释:

了解基本的Haskell错误讯息


Laziness, strictness, guarded recursion

演示

let a = 1 : a -- guarded recursion, (:) is lazy and can be pattern matched.
let (v : _) = a
> v
1
> head a -- head a == v
1

let a = 1 * a -- not guarded, (*) is strict
> a
*** Exception: <<loop>>

IO

glaebhoerl在Reddit讨论串的留言:

有趣的补充笔记: GHC需要将state token representation隐藏在抽象的IO类型后面, 因为state token必须线性地使用,不能复制或丢弃,但类型系统无法强制这件事。 某个干净、lazy、类似Haskell的语言有uniqueness特性(类似linear type,但可能有些 我没意识到的细微差别),为了方便,它直接暴露World-passing并提供非抽象的IO monad。

Monads and monad transformers

在你了解typeclasses、Monoid、Functor和Applicative之前,请不要做下列练习!

尝试自行实现标准函式库中的monads(List、Maybe、Cont、Error、Reader、Writer、State),可以让你 更了解它们。再来,不妨尝试用下述技术实现一个小型expression language的monadic解释器: Monad Transformers Step by Step(在下列monad transformer章节亦有提及)

通过用不同的monad改变语意,从而产生不同的解释器,help convey what's going on。

再来,实现Control.Monad中的函数,例如:mapMsequence是个练习撰写generic monadic code的好机会。

前面提到过的FP课程也可以用来当这个过程的指南,它也包括了如何撰写你自己的Applicative。

Credits:

Monad transformers

Testing, tests, specs, generative/property testing

  • Kazu Yamamoto的这篇教学堪称典范!

  • Simple-Conduit:这个简单的函式库对于学习IO串流如何工作很有帮助, 所学亦可应用在其他函式库,例如Pipes和Conduit。

Parsing in Haskell

Parsing与产生JSON

Aeson是Haskell标准的JSONparsing解决方案。你可以从hackagegithub取得。

图算法与数据结构

开发环境

Emacs

Vim

Sublime Text

Cabal常见问答

一篇超赞的常见问答

不但对各种主题都有很好的导览,也包含了Cabal的一些重要基础。

Cabal导览

在引入沙箱(sandbox)前,Cabal地狱(Cabal Hell)对所有Haskell使用者来说都是一大问题。 在沙箱外安装的套件会直接装在你的用户套件资料库(user pacakge-db)中。除非是常用的基础套件, 例如Cabal、alex、happy等,这绝不是个好方法。除非你很清楚你自己在做什么,任何套件都不该 安装在用户资料库或全域资料库(global package-db)。

这里有些如何避免Cabal地狱的最佳指南

如果要实验新套件,或是起始新专案,在一个新目录中执行cabal sandbox init

简言之:

  • 无论是安装新套件、建置新旧专案、做任何实验,请用沙箱。
  • cabal repl来启动project-scoped ghci实体。

我所建议这种以沙箱为基础的方式,应该可以避免套件相依性的问题。但这与Haskell Platform提供 预先编译套件的方法不相容。如果你还在学习Haskell,而且不太了解ghc-pkg和Cabal如何运作, 不要用Haskell Platform,改用前面所提的安装方式。

Stackage

如果你面临一些构建上的问题(特别是Yesod),不妨考虑用Stackage:

据作者所言,Stackage通常比cabal freeze更实用。

Hoogle与Haddock

依类型签名搜索代码

Hoogle搜索引擎可依型别搜寻。

比方说,请看以下搜索(a -> b) -> [a] -> [b]的结果:

搜索结果.

fpcomplete所管理的在此

另外Hayoo预设开启了对所有hackage的搜寻。

设定你自己本地端的Hoogle

详细方法请看这篇文章

Haddock

  1. 修正你的hackage文件Fix your hackage documentation

  2. Hackage文件第二版Hackage documentation v2

请注意,以上这些文章都有些过期,例如:现在Hacakge已支援shiny new info with documentation info and build status.

真正重要的事

为了让haddocks含入相关套件的文件,你必须在~/.cabal/config设立ducumentation: True。如果它被设为False,或间接被default(False)关闭,你会需要删除并重新安装所有套件,再产生haddocks。

请记住,因为$pkg参数会被cabal内插,html-locationcontent-location参数必须以单引号括入,再插入shell命令或包含在shell脚本中。在Makefile中是不行的,因为它会被当作Make的变数!

#! /usr/bin/env sh

# 如果把反斜线去掉,你可以把它写成一行
cabal haddock --hoogle --hyperlink-source \
 --html-location='http://hackage.haskell.org/package/$pkg/docs' \
 --contents-location='http://hackage.haskell.org/package/$pkg'

TravisCI

如果你跟我一样,是TravisCI的超级粉丝,那我强力建议你参考multi-ghc-travis为你的Haskell专案的travis.yml作基础。

前端/JavaScript

我们的选择多得惊人!我个人推荐三种:

我该用哪一种前端语言?

GHCJS和Haste都是纯Haskell,GHCJS比Haste能和更多的Haskell套件相容,但这不会影响大多数的前端专案。PureScript并非Haskell,因此无法直接和你的后端共享源码。

GHCJS的执行期payload是最大的,大约100kb (luite正在研究如何解决此问题),Haste则和PureScript差不多。

PureScript有最好的JS工具链整合(用gulp/grunt/bower),GHCJS和Haste则与Haskell工具链整合较好(例如Cabal)。

以上三者都是极佳选择,大多数的前端专案都适用。

想要更充分了解laziness、NF、WHNF

关于lazy lambda calculus的研究论文

并行/并发(Parallelism/Concurrency)

Lenses and Prisms

在你习惯Haskell后,我强烈建议你学习Lenses与Prisms。你不必了解底层的原理,只要当一个使用者,就很受用。

大家普遍误会Lens是个很难用的东西,其实任何一个了解Functor/Foldable/Traversable,甚至只知道Functor的人,都可以运用Lenses与Prisms来让他们的开发生涯更快乐。

如果你曾经做过:(fmap . fmap),你其实已经有Lense的思维了。

我推荐以下两篇教学:

详细资料请看这里:Lens package on hackage.

递归范式(Recursion Schemes)

你一定听过些疯狂的『*-morphism』,他们其实只是递归。在尝试搞懂前,你应该要先知道如何为list以及至少一种其他数据结构实现foldr,例如tree (folds叫做catamorphisms)。再进一步了解如何在以上数据结构实现unfold (anamorphism)会让整体知识完善些。

以下资料与traversable和foldable的概念相合。

GHC Core与效能调校

类型(Type)与范畴论(Category Theory)

写Haskell不用学,仅供有兴趣的人参考!

如果你想开始学习类型与范畴论:

书籍

Stephen俏皮的"How to get to monad"文章

其他有趣的主题

Parametricity, ad-hoc vs. parametric polymorphism, free theorems

Initial与Final、DSLs、与Tagless

Comonads

Yoneda / CoYoneda

Propositions vs. Judgments (computation)

Dependent typing

静态链接二进制档 Statically linking binaries

补充资料

有部分已在本文提及

对话记录

本储存库中

里面有些非常重要而有帮助的资讯,可协助你深入了解许多不同的议题。