Haskell入门


755

几天来,我一直试图围绕Haskell的函数式编程范例。我通过阅读教程和观看截屏视频来做到这一点,但似乎没有任何坚持。现在,在学习各种命令式/ OO语言(例如C,Java,PHP)时,练习已经成为我的理想选择。但是由于我真的不知道Haskell的功能,并且因为要使用许多新概念,所以我不知道从哪里开始。

那么,您是如何学习Haskell的?是什么让您真正“破冰”?另外,对于开始练习有什么好主意吗?


Answers:


2476

我将根据您在Haskell中的技能水平来订购本指南,从绝对的初学者到专家。请注意,此过程将花费数月(数年?),因此相当长。

绝对的新人

首先,Haskell具有足够的技能,能够胜任任何工作。它非常快(据我的经验仅落后于C和C ++),并且可以用于从仿真到服务器,GUI和Web应用程序的任何内容。

但是,有些问题对于Haskell的初学者来说比其他问题更容易编写。数学问题和列表处理程序是此的理想选择,因为它们只需要最基本的Haskell知识就可以编写。

首先,一些好的导游学习Haskell非常基本的是快乐学习的Haskell教程和第6章学习你一个Haskell。在阅读这些内容时,最好也用已知的知识解决简单的问题。

另外两个很好的资源是第一原理的Haskell编程Haskell编程。它们都附带有每章的练习,因此您会遇到一些小问题,这些问题与您在最后几页中学到的内容相匹配。

haskell 99个问题页面是一个很好的尝试列表。这些从最基本的开始,并且随着您的前进而变得越来越困难。这是一个很好的实践,因为它们可以让您练习递归和高阶函数的技能。我建议跳过任何需要随机性的问题,因为在Haskell中这要困难一些。如果您想使用QuickCheck测试解决方案,请检查此SO问题(请参阅下面的“ 中级”)。

一旦完成其中一些操作,就可以继续进行一些Euler项目的问题。这些是按完成的人数排序的,这很好地说明了困难。这些测试比起先前的问题,对您的逻辑和Haskell的测试更多,但是您仍然应该能够完成前几个问题。Haskell处理这些问题的一大优势是Integer的大小不受限制。要解决其中的一些问题,请阅读第7章和第8章,以了解Haskell,这对您很有用。

初学者

在那之后,您应该对递归和高阶函数有一个很好的处理,因此这是开始处理一些实际问题的好时机。Real World Haskell是一个很好的起点(在线书籍,您也可以购买印刷版)。我发现前几章对那些从未做过函数编程/使用过递归的人介绍得太快了。但是,通过实践,您可能会遇到以前的问题,您会发现它完全可以理解。

解决本书中的问题是学习如何在Haskell中管理抽象和构建可重用组件的好方法。这对于习惯面向对象(oo)编程的人们至关重要,因为普通的oo抽象方法(oo类)不会出现在Haskell中(Haskell具有类型类,但它们与oo类有很大不同,更像是oo接口) )。我认为跳过章节不是一个好主意,因为每个章节都引入了很多新思想,这些新思想将在以后的章节中使用。

一段时间后,您将进入第14章,即可怕的monads章(dum dum dummmm)。几乎每一个学习Haskell的人都很难理解单子,因为这个概念太抽象了。我想不出其他语言中的任何概念都像函数式编程中的monad一样抽象。Monads允许将许多创意(例如IO操作,可能失败的计算,解析等)统一在一个创意下。因此,如果在阅读monad章节后还不太了解它们,请不要感到沮丧。我发现阅读许多有关monad的不同解释很有用;每个人都对该问题提出了新观点。这是一个非常好的monad教程列表。我强烈推荐All About Monads,但其他的也都不错。

同样,要使这些概念真正融入还需要一段时间。这既要通过使用,也要经过一段时间。我发现有时候睡在一个问题上比什么都重要!最终,这个想法会响起,您会想知道为什么您难以理解一个实际上非常简单的概念。发生这种情况真是棒极了,而且确实如此,您可能会发现Haskell是您最喜欢的命令式编程语言:)

为了确保您完全理解Haskell类型系统,您应该尝试解决20个中间的haskell练习。这些练习使用有趣的函数名称(例如“ furry”和“ banana”),并且如果您还没有基本的函数编程概念,则可以帮助您更好地理解它们。用一堆纸包裹着箭头,独角兽,香肠和毛茸茸的香蕉的好方法,度过一整夜。

中间

了解Monad之后,我认为您已经从初学者Haskell程序员过渡到中级haskeller。那么从这里去哪里呢?我建议的第一件事(如果您还没有从学习单子学到它们的话)是各种类型的单子,例如Reader,Writer和State。再次,真实世界的Haskell和All about monads对此做了很好的报道。要完成您的monad培训,必须学习有关monad变压器的知识。这些使您可以将不同类型的Monad(例如Reader和State monad)组合为一个。开始时这似乎没有用,但是使用了一段时间后,您会想知道没有它们的生活。

现在,您可以根据需要完成真实世界的Haskell书。现在只要跳过单子,跳过章节就不再重要了。只需选择您感兴趣的内容即可。

有了您现在所掌握的知识,您应该能够使用cabal上的大多数软件包(至少有文档的...),以及Haskell附带的大多数库。可以尝试的有趣库的列表为:

  • Parsec:用于解析程序和文本。比使用正则表达式好得多。出色的文档,也有真实世界的Haskell章节。

  • QuickCheck:一个非常酷的测试程序。您要做的是写一个始终为true的谓词(例如length (reverse lst) == length lst)。然后,您通过谓词QuickCheck,它将生成许多随机值(在本例中为列表),并测试所有结果的谓词为真。另请参见在线手册

  • HUnit:Haskell中的单元测试。

  • gtk2hs:Haskell最受欢迎的gui框架,可让您在Haskell中编写gtk应用程序。

  • happstack:Haskell的Web开发框架。不使用数据库,而是使用数据类型存储。相当不错的文档(其他流行的框架将是snapyesod)。

另外,您最终应该学习许多概念(例如Monad概念)。这比第一次学习Monad容易,因为您的大脑将习惯于处理所涉及的抽象级别。Typeclassopedia是了解这些高级概念以及它们如何组合的很好的概述。

  • 适用性:类似于Monads的界面,但功能较弱。每个Monad都是适用的,但反之则不然。这很有用,因为有些类型是可应用的,但不是Monads。而且,使用Applicative函数编写的代码通常比使用Monad函数编写等效代码更容易组合。请从了解haskell指南中查看函子,适用函子和Monoids

  • FoldableTraversable:抽象列表的许多操作的类型类,以便可以将相同的功能应用于其他容器类型。另请参见haskell Wiki解释

  • 独异:一个半群是具有一个零(或mempty)值的类型和操作,谱写<>联接两个幺在一起,使得x <> mempty = mempty <> x = xx <> (y <> z) = (x <> y) <> z。这些被称为身份和关联法。许多类型是Monoid,例如带有mempty = 0和的数字<> = +。这在许多情况下很有用。

  • 箭头:箭头是表示接受输入并返回输出的计算的一种方式。函数是最基本的箭头类型,但还有许多其他类型。该库还具有许多非常有用的用于操纵箭头的函数-即使仅与普通的旧Haskell函数一起使用,它们也非常有用。

  • 数组:Haskell中的各种可变/不可变数组。

  • ST Monad:使您可以编写具有可变状态的代码,该状态可以非常快速地运行,同时仍保持纯净的状态。请参阅链接查看更多细节。

  • FRP:Functional Reactive Programming,一种新的实验性编写方式,用于处理事件,触发器,输入和输出(例如gui)的代码。我对此不太了解。保罗·哈达克(Paul Hudak)谈论yampa是一个良好的开端。

您应该查看许多新的语言功能。我只列出它们,您可以从google,haskell Wikibook,haskellwiki.org网站和ghc文档中找到许多有关它们的信息。

  • 多参数类型类/功能依赖性
  • 类型家庭
  • 现有量化类型
  • 幻影类型
  • 技术
  • 其他...

许多Haskell基于类别理论,因此您可能需要研究一下。一个很好的起点是计算机科学家的范畴论。如果您不想买这本书,那么作者的相关文章也很棒。

最后,您将想了解有关各种Haskell工具的更多信息。这些包括:

  • ghc(及其所有功能)
  • cabal:Haskell软件包系统
  • darcs:用Haskell编写的分布式版本控制系统,在Haskell程序中非常流行。
  • haddock:Haskell自动文档生成器

在学习所有这些新库和概念时,在Haskell中编写一个中等大小的项目非常有用。它可以是任何东西(例如小型游戏,数据分析器,网站,编译器)。为此,您将可以应用现在正在学习的许多东西。您会在这个级别上停留很长时间(这就是我所在的位置)。

专家

到这个阶段需要花很多年的时间(您好,2009年开始!),但是我猜您从这里开始编写phd论文,新的ghc扩展,并提出新的抽象概念。

获得帮助

最后,在学习的任何阶段,都有很多获取信息的地方。这些是:

  • #haskell IRC频道
  • 邮件列表。这些都是值得阅读的,仅供阅读正在发生的讨论-有些非常有趣。
  • haskell.org主页上列出的其他地方

结论

好吧,结果竟然比我预期的要长...无论如何,我认为精通Haskell是一个非常好的主意。这需要很长时间,但这主要是因为您正在学习一种全新的思维方式。这不像在学习Java之后学习Ruby,而是像在学习C之后学习Java。另外,我发现学习Haskell可以提高我的面向对象编程技能,因为我看到了许多抽象思想的新方法。


35
耶箭!首先,您让单子形成大脑,然后站在头上思考一下彗星,然后同时执行两个操作以获取箭头:) Haskell中有很多表达能力可以通过类型级别来打开编程。
短暂

13
@nanothief Monad功能更强大,但结构也更少……许多人在无法使用更简洁代码的情况下使用monad Applicative。多数是Functors也是Monads,但是您不会四处使用>>=return何时fmap才能满足要求,因为如果可以使用后者,它将导致更简单的代码。
汤姆·克罗基特

8
@pelotom,我添加了typeclassopedia链接以及在该部分使用Applicative的更好理由,并删除了Functor部分。由于大多数教材(包括RWH)都强调Monad,因此很难以正确的顺序排列Monad和Applicative概念。另一方面,自从我最初编写答案(将近2年:O)以来,教您haskell教程已经走了很长一段路,并且确实在Monad之前教了Applicative,也许现在应该是学习haskell的推荐方法。
David Miani

2
很好的建议。我是一年多以前开始的,并且整个过程都是中级阶段。反馈:RWH的monad章节(第14章)解释不充分。阅读RWH的在线版本是有好处的,因为它包含有助于本章的众包注释。FWIW,您可能已经发明了Monad,这是最适合我的monad教程。
汤姆(Tom)

6
@tomf:谢谢!我一直对这个答案的出色表现感到惊讶-自从我写它以来已经过去了五年,但是它仍然很强大。我将需要尽快对其进行更新,因为它已经过时了。它没有提到透镜,管道,约束种类,haskell平台,类型级别数字,而且自编写以来,它们是相当重要的新主题。没错,RWH不再那么好,很长时间没有更新,而且很多示例都没有编译。我很高兴无论如何仍然对您有帮助。
David Miani 2014年

179

我的一些同事在“ 了解Haskell for Great Good”方面拥有丰富的经验

教程针对的是具有命令式编程语言经验,但以前没有使用功能性语言进行编程的人员。

并核对答案在这里


27
我第二。另外,由于不明显,因此这里是该教程的可下载pdf版本的链接:learnyouahaskell.com/learnyouahaskell.pdf该网页设计很棒,但是我也想复制地铁的副本。
Telemachus

8
我从此开始,但我认为您应该直接去Real World Haskell。区别就好像是从K&R或C到“傻瓜C”学习C一样,它试图变得简单,但是却错过了一些重要的东西。我认为最好直接弄清楚事实,而不是尝试学习Haskell“命令式方法”。
约翰·史密斯,2009年

7
我绝对喜欢这个,并且我已经花了很多时间在这个和Real World Haskell上。IMO,“了解Haskell”比真实世界的Haskell提供了更深刻的见解,尽管它们都是很好的资源。
查理·

7
@ abababa22我认为最好先阅读LYAH,然后再去RWH。LYAH不仅教您Haskell,它教您函数式编程。解决问题时,您便开始以实用的方式进行思考。显然,仅LYAH不足以编写大型应用程序,但这会使您以正确的方式屈服。如果您来自命令性背景,这是最好的方法,IMO
Abdulsattar Mohammed

4
@Telemachus请注意:PDF不是最终版本,至少缺少最后一章。
sdcvvc

103

这是一本可以在线阅读的好书:Real World Haskell

我完成的大多数Haskell程序都是用来解决Euler项目的问题。

我不久前读到的一条建议是,您应该拥有一套标准的简单问题,并且您知道如何解决(理论上),然后,每当您尝试学习一种新语言时,便会以该语言实现这些问题。


2
根据我的经验,在您进入第5章之前,真实世界的Haskell很棒。从那时起,我就不推荐它。
2014年

为什么是@MasterMastic?第5章以外的问题是什么?我想知道花钱之前。
杰·布兰查德

@JayBlanchard在第5章中,您开始获得一个具体的库示例,这很好,但是他们告诉您他们将要做什么,要这样做,但是他们没有完全解释原因,也没有清楚地解释,并且相当多的魔术十六进制字面量。您只是在进行动作。对我而言,这不是最大的问题,最大的问题是,本书在很大程度上依赖于这类艰巨而冗长的示例(足够长,可以花整整整一章的时间)。您几乎无法阅读想要的部分。我认为伟大的作家,惊人的知识,但极为执行力差。
2014年


69

要补充其他人的答案-有一个有用的工具,可以帮助您在编码时(例如,在解决项目Euler问题时): Hoogle。您可以使用命令行界面或Web界面

命令行

安装Haskell平台后,请确保 cabal install hoogle

Hoogle用法示例:

您具有一个函数,f x = 3 * x + 1并且想要将其应用于(5 :: Int),然后将其应用于结果以及该结果等等,以获取这些值的无限列表。您怀疑可能已经存在可以为您提供帮助的功能(f尽管不是专门针对您的)。

该函数将类型的(a -> a) -> a -> [a],如果它需要f 5或者a -> (a -> a) -> [a]如果它需要5 f(我们假设该功能对于一般类型,而不仅仅是Int为s)

$ hoogle "a -> (a -> a) -> [a]"
Prelude iterate :: (a -> a) -> a -> [a]

是的,您需要的函数已经存在,并且称为iterate。你用它iterate func 5

网页界面

相同示例的结果可以在此处找到。


一旦了解了如何向Hoogle询问所需的内容,便可以轻松找到所需的标准库函数。
ankh-morpork 2015年

57

格雷厄姆·赫顿(Graham Hutton)的《Haskell编程》简洁明了,相当详尽,他在Haskell任教的年限确实很出色。无论您从哪里去,我几乎总是建议人们从这里开始。

特别是,第8章(“功能解析器”)提供了开始处理monad所需的真正基础,我认为到目前为止是最好的起点,其次是All About Monads。(不过,关于该章,请注意网站上的勘误表:但是,如果do没有一些特殊帮助,您将无法使用该表单。您可能想先了解类型类,然后自行解决该问题。)

Haskell的初学者很少强调这一点,但是值得尽早学习,不仅涉及使用monad,还涉及构建自己的monad。这并不难,定制的任务可以使许多任务变得更加简单。


5
这是一本完全未被重视的书(和答案)。关于函数解析器的章节,接着是关于IO的章节,都没有提到monad,这确实是一种优雅的教学方法。
michiakig 2012年


31

我建议您加入#haskell irc频道并在那里提问。这就是我学习Haskell的方式。如果按照上面的建议进行“真实世界” Haskell的操作,则对问题的实时解答会很有帮助。#haskell上有很多聪明的人写Haskell是为了娱乐和牟利,所以您会得到很多好的建议。尝试一下!


5
+1 -需要明确的是:不要学习它只是与IRC频道。在这种情况下,不要问“如何编写haskell程序?如何加数字?”。
可替代

除了irc freenode之外,最近在Discord聊天中对haskell的讨论也越来越活跃。
typelogic


19

我还可以推荐“ 另一个Haskell教程”作为简介。

Brent Yorgey的Typeclassopedia是另一个很好的学习资源(可能是中级水平),对我有很大帮助,但在其他答案中并未提及,可以在《 Monad Reader》(问题)中找到。13)

它以易于访问的方式编写,并包含(除其他事项外)以下介绍性建议:

Haskell专家的智慧有两个秘诀:

  1. 了解类型。

  2. 通过熟悉许多示例,对每个类型类及其与其他类型类的关系都有深刻的了解。

Monad Reader本身对于函数式程序员(不仅仅是Haskell程序员)是绝对的宝库。


14

尝试在其中编写简单的程序。

您可能会在各种教科书中找到示例任务。

我不建议您坚持使用Haskell / FP教科书,而只想尝试做一些简单的事情:计算,字符串操作,文件访问。

我解决了一打之后,我就破冰了:)

在那之后,请阅读许多高级概念(Monads,Arrows,IO,递归数据结构),因为haskell是无限的,并且它们很多。


14

我确实认为通过示例实现Haskell的功能是最重要的最佳方法。

http://en.wikipedia.org/wiki/Haskell_98_features

这是棘手的类型类,包括单子和箭头

http://www.haskell.org/haskellwiki/Typeclassopedia

对于现实世界中的问题和更大的项目,请记住以下标签:GHC(最常用的编译器),Hackage(libraryDB),Cabal(建筑系统),darcs(另一个建筑系统)。

集成系统可以节省您的时间:http : //hackage.haskell.org/platform/

该系统的软件包数据库:http : //hackage.haskell.org/

GHC编译器的Wiki:http : //www.haskell.org/haskellwiki/GHC

在Haskell_98_features和Typeclassopedia之后,我认为您已经可以自己找到并阅读有关它们的文献资料。

顺便说一句,您可能想测试某些GHC的语言扩展,将来可能会成为haskell标准的一部分。

这是学习Haskell的最好方法。我希望它可以帮助您。


13

我建议您首先阅读BONUS的教程,然后阅读Real World Haskell(免费在线)。加入irc.freenode.com上#Haskell IRC频道,并提出问题。这些人绝对是新手友好的,并且随着时间的推移对我有很大帮助。另外,在SO上,这里是获得您无法掌握的事情的帮助的好地方!尽量不要气disc,一旦它发出喀哒声,您的头脑就会被震撼。

BONUS的教程将使您入门,并为Real World Haskell带来的刺激旅程做好准备。祝你好运!


12

如果您只有使用命令式/ OO语言的经验,我建议您使用更常规的功能语言作为垫脚石。Haskell 确实与众不同,您必须了解许多不同的概念才能到达目的地。我建议首先处理ML风格的语言(例如F#)。


榆木可能是这些替代品中最接近,更有用和对初学者友好的……
Pedro Rolo

1
我不同意通过F#之类的临时路线。对我来说,这就像喝伏特加酒一样,您必须迅速喝一口。这样更痛苦,但也有乐趣。临时路线,只会给我带来更多的困惑。
typelogic

10

第一个答案是一个很好的答案。为了达到专家级的水平,您应该与一些专家本人进行博士学位。

我建议您访问Haskell页面:http : //haskell.org。那里有很多材料,并且有很多由Haskell社区认可的Haskell最新资料的参考。


2
抱歉,但是在这里使用PhD参数就像是说您必须拥有300美元的厨刀才能成为好厨师。甚至Haskell的父亲Simon Peyton Jones也没有博士学位。实践和坚持不懈是导致在此领域及任何其他领域获得专业知识的原因。
Petras Purlys
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.