开始使用Haskell

几天来,我一直在努力学习Haskell中的函数式编程范式。我通过阅读教程和观看截屏来做到这一点,但似乎没有什么真正坚持下去。 现在,在学习各种命令式/OO语言(如C、Java、PHP)时,练习对我来说是一个很好的方式。但是由于我真的不知道Haskell有什么能力,并且因为有许多新概念可以利用,我不知道从哪里开始。

那么,你是如何学习Haskell的?是什么让你真正“打破僵局”的?还有,开始练习有什么好主意吗?

268353 次浏览

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

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

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

在我解决了一打之后,我打破了僵局:)

之后,阅读大量高级概念(单子,箭头,IO,递归数据结构),因为haskell是无限的,而且有很多。

这里有一本你可以在线阅读的好书:真实世界Haskell

我做过的大多数Haskell程序都是为了解决Project Euler问题。

不久前我读到的一条建议是,你应该有一套标准的简单问题,你知道如何解决(理论上),然后每当你尝试学习一门新语言时,你就用那门语言实现这些问题。

我的一些同事对为你学习一个伟大的Haskell!有很好的经验。

教程针对那些有 有命令式编程经验 语言,但尚未编程 之前的函数式语言。

并检查答案这里

不要试图阅读所有带有有趣隐喻的monad教程。它们只会让你变得更糟。

我建议加入#haskell irc通道并在那里提问。这就是我学习Haskell的方式。如果你按照上面的建议使用真实世界的Haskell,实时回答你的问题将非常有帮助。#haskell上有很多聪明人写Haskell是为了好玩和盈利,所以你会得到很多好的输入。试试吧!

我建议你先从阅读BONUS教程开始,然后阅读真实世界Haskell(免费在线)。加入#Haskell IRC频道,irc.freenode.com,并提出问题。这些人对新手非常友好,并且随着时间的推移帮助了我很多。而且,在SO上是一个获得帮助的好地方,可以帮助你解决你无法掌握的事情!尽量不要气馁,一旦它点击,你的头脑就会被炸飞。

BONUS教程会让你兴奋起来,让你为现实世界Haskell带来的刺激之旅做好准备。祝你好运!

我将根据您在Haskell中的技能水平来订购本指南,从绝对的初学者到专家。请注意,这个过程需要几个月(几年?),所以它相当长。

绝对初学者

首先,Haskell可以做任何事情,只要有足够的技能。它非常快(在我的经验中仅次于C和C++),可以用于从模拟到服务器、guis和Web应用程序的任何事情。

然而,对于Haskell初学者来说,有些问题比其他问题更容易编写。数学问题和列表过程程序是很好的候选人,因为它们只需要最基本的Haskell知识就可以编写。

一些学习Haskell基础知识的好指南是快乐学习Haskell教程为你学习一个伟大的Haskell(或其JupyterLab改编)的前6章。阅读这些时,用你所知道的解决简单问题是一个非常好的主意。

另外两个很好的资源是Haskell编程的第一原则在Haskell中编程。它们都为每一章提供了练习,所以你有一些小的简单问题与你在最后几页学到的相匹配。

一个很好的问题列表是haskell 99问题页面。这些从非常基本的开始,随着你的继续变得越来越困难。做很多这样的练习是非常好的,因为它们让你练习递归和高阶函数的技能。我建议跳过任何需要随机性的问题,因为这在Haskell中有点困难。如果你想用QuickCheck测试你的解决方案,请检查这个so问题(参见下面的中级)。

完成了其中的一些之后,你就可以继续做一些Project Euler问题了。这些问题是根据有多少人完成了它们而排序的,这是一个相当好的难度指示。与之前的问题相比,这些问题更考验你的逻辑和Haskell,但你应该仍然能够完成前几个。Haskell处理这些问题的一大优势是整数不受大小限制。要完成其中一些问题,阅读《向你学习Haskell》的第7章和第8章会很有用。

初学者

在那之后,你应该对递归和高阶函数有了相当好的处理,所以这将是开始做一些更现实世界问题的好时机。一个非常好的起点是真实世界Haskell(在线书籍,你也可以购买硬拷贝)。我发现前几章对从未做过函数式编程/使用过递归的人来说介绍得太快了。然而,通过你做前面问题的练习,你应该会发现它完全可以理解。

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

过一会儿你会读到第14章,可怕的monads章节。几乎每个学习Haskell的人都很难理解monads,因为它的概念是多么抽象。我想不出在另一种语言中有任何概念像函数式编程中的monads一样抽象。monads允许许多想法(例如IO操作、可能失败的计算、解析……)统一在一个想法下。所以如果读完monads章节后你还不真正理解它们,不要感到气馁。我发现阅读许多不同的monads解释很有用;每一个都提供了一个新的视角来看待问题。这是一个非常好的monad教程列表。我强烈推荐关于Monads的一切,但其他的也很好。

而且,真正理解概念需要一段时间。这需要通过使用,但也需要通过时间。我发现有时候睡在问题上比什么都有帮助!最终,这个想法会点击,你会想知道为什么你很难理解一个实际上非常简单的概念。发生这种情况真是太棒了,当它发生时,你可能会发现Haskell是你最喜欢的命令式编程语言:)

为了确保您完全理解Haskell类型系统,您应该尝试解决20个中间haskell练习。这些练习使用有趣的函数名称,如“毛茸茸的”和“香蕉”,并帮助您很好地理解一些基本的函数式编程概念,如果您还没有这些概念。与一堆覆盖着箭头,独角兽,香肠和毛茸茸的香蕉的论文度过夜晚的不错方式。

中级

一旦你理解了Monad,我认为你已经从一个初学者Haskell程序员过渡到一个中级haskeller了。那么接下来该怎么做呢?我要推荐的第一件事(如果你还没有从学习monad中学到它们)是各种类型的monad,比如Reader、Writer和State。同样,Real world Haskell和All about monads对此有很好的介绍。要完成你的monad培训,学习monad变压器是必须的。这些可以让你将不同类型的monad(比如Reader和State monad)组合成一个。这可能一开始看起来没有用,但是使用它们一段时间后,你会想知道没有它们你是怎么生活的。

现在,如果你愿意,你可以完成现实世界的Haskell书。现在跳过章节并不重要,只要你有单子。只要选择你感兴趣的。

根据你现在掌握的知识,你应该能够使用Cabal上的大多数包(至少有文档记录的包…),以及Haskell附带的大多数库。一个有趣的库列表是:

  • Parsec:用于解析程序和文本。比使用正则表达式好得多。优秀的留档,还有一个真实世界的Haskell章节。

  • 快速检查:一个非常酷的测试程序。你所做的是编写一个应该始终为真的谓词(例如length (reverse lst) == length lst)。然后你将谓词传递QuickCheck,它将生成很多随机值(在这种情况下是列表)并测试谓词对所有结果是否为真。另见在线手册

  • HUnit:Haskell中的单元测试。

  • gtk2hs:最流行的Haskell GUI框架,可让您编写gtk应用程序。

  • 幸福堆栈:Haskell的Web开发框架。不使用数据库,而是数据类型存储。非常好的文档(其他流行的框架是Snapyesod)。

此外,还有许多概念(如Monad概念)你最终应该学习。这将比第一次学习Monad更容易,因为你的大脑将习惯于处理所涉及的抽象级别。学习这些高级概念以及它们如何组合在一起的一个非常好的概述是类型学

  • 应用:类似于Monad的接口,但功能较弱。每个Monad都是应用的,但不是相反。这很有用,因为有些类型是应用的,但不是Monad。此外,使用应用函数编写的代码通常比使用Monad函数编写等效代码更具可组合性。请参阅泛函、应用泛函和半群从学习你一个haskell指南中。

  • 可折叠可穿越:抽象列表的许多操作的类型类,以便相同的功能可以应用于其他容器类型。另请参阅haskell wiki解释

  • 莫诺:一元类是一个值为零(或毫空)的类型,以及一个操作,标记为<>,它将两个一元类连接在一起,例如x <> mempty = mempty <> x = xx <> (y <> z) = (x <> y) <> z。这些称为同一性和结合性定律。许多类型是一元类,例如数字,带有mempty = 0<> = +。这在许多情况下都很有用。

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

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

  • st monad:允许您编写具有可变状态的代码,该状态运行非常快,同时在monad之外仍然保持纯状态。有关更多详细信息,请参阅链接。

  • FRP:函数式响应式编程,一种新的、实验性的代码编写方式,用于处理事件、触发器、输入和输出(例如gui)。虽然我对此了解不多。保罗·胡达克在说山巴是一个好的开始。

有很多新的语言特性你应该看看。我只是列出它们,你可以从谷歌、haskell wikibook、haskellwiki.org网站和ghc留档找到很多关于它们的信息。

  • 多参数类型类/函数依赖项
  • 类型家庭
  • 存在量化类型
  • 幻影类型
  • GADTS
  • 其他…

很多Haskell都是基于范畴理论的,所以你可能想研究一下。一个很好的起点是计算机科学家的范畴理论。如果你不想买这本书,作者的相关文章也很棒。

最后,您将需要了解有关各种Haskell工具的更多信息。其中包括:

  • ghc(及其所有功能)
  • 阴谋集团:Haskell包系统
  • Darcs:用Haskell编写的分布式版本管理系统,在Haskell程序中非常流行。
  • 黑线鱼:Haskell自动留档生成器

在学习所有这些新的库和概念的同时,用Haskell编写一个中等规模的项目是非常有用的。它可以是任何东西(例如小游戏、数据分析器、网站、编译器)。致力于此将使你能够应用你现在正在学习的许多东西。你可以在这个水平上停留很长时间(这就是我的位置)。

专家

你需要几年的时间才能达到这个阶段(你好,从2009年开始!),但从这里开始,我猜你开始写博士论文,新的ghc扩展,并提出新的抽象。

寻求帮助

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

  • #haskell irc频道
  • 邮件列表。这些值得注册,只是为了阅读正在进行的讨论——有些非常有趣。
  • haskell.org主页上列出的其他地方

结论

这比我预期的要长……不管怎样,我认为精通Haskell是一个非常好的想法。这需要很长时间,但这主要是因为你通过这样做学习了一种全新的思维方式。这不像学习Java后学习Ruby,而是像学习C后学习Java。此外,我发现我的面向对象编程技能也因为学习Haskell而提高,因为我看到了许多抽象想法的新方法。

添加别人的答案-有一个有用的,将帮助你编码时(例如,当解决项目欧拉问题): Hoogle。您可以使用命令行界面或web界面

命令行

安装Haskell平台后,请务必cabal install hoogle

Hoogle使用示例:

你有一个函数f x = 3 * x + 1,你想将它应用于(5 :: Int),然后将它应用于结果和该结果等等,并获得这些值的无限列表。你怀疑可能已经存在一个函数来帮助你(虽然不是专门针对你的f)。

如果需要f 5,则该函数的类型为(a -> a) -> a -> [a];如果需要5 f,则该函数的类型为a -> (a -> a) -> [a](我们假设该函数适用于一般类型,而不仅仅是Ints)

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

是的,您需要的函数已经存在,它被称为iterate。您在iterate func 5使用它!

网页界面

可以找到相同示例的结果这里

Graham Hutton的在Haskell中编程简明扼要,相当透彻,他多年来教授Haskell的经验也显示了这一点。无论你从哪里开始,我几乎总是建议人们从它开始。

特别是,第8章(“函数解析器”)提供了开始处理monad所需的真正基础,我认为这是迄今为止最好的开始,其次是关于Monads的一切。(不过,关于那一章,请注意网站上的勘误表:没有一些特殊帮助,你不能使用do表单。你可能想先了解类型类并自己解决这个问题。)

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

如果你只有命令式/OO语言的经验,我建议使用更传统的函数式语言作为垫脚石。Haskell与真的不同,你必须理解很多不同的概念才能到达任何地方。我建议先处理ML风格的语言(例如F#)。

第一个答案非常好。为了达到专家级别,你应该和一些专家自己一起攻读博士学位。

我建议您访问Haskell页面:http://haskell.org。在那里您有很多材料,以及对Haskell社区批准的最新Haskell内容的大量引用。

我喜欢看这个关于使用Haskell进行函数式编程的13集系列。

C9讲座:埃里克·梅耶尔博士-函数式编程基础: http://channel9.msdn.com/shows/Going+Deep/Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1/

我还可以推荐又一个Haskell教程作为介绍。

另一个很好的学习资源(可能是中级水平),它对我帮助很大,而且在我所看到的其他答案中没有提到,是Brent Yorgey的类型学,可以在单子读者(第13期)中找到。

它以非常容易理解的风格编写,并包含(除其他外)以下介绍性建议:

专家Haskell黑客的智慧有两个关键:

  1. 了解类型。

  2. 对每个类型类及其与其他类型类的关系获得深刻的直觉 类型类,通过熟悉许多示例来支持。

单子读者本身是函数式程序员(不仅仅是Haskell程序员)的绝对宝库。

这些是我的最爱

Haskell:使用类型进行函数式编程

Joeri van Eekelen, et al. | Wikibooks
Published in 2012, 597 pages

真实世界的Haskell

   B. O'Sullivan, J. Goerzen, D. Stewart | OReilly Media, Inc.
Published in 2008, 710 pages

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

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

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

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

对于现实世界的问题和更大的项目,请记住这些标签:GHC(最常用的编译器)、Hackage(图书馆数据库)、Cabal(构建系统)、darcs(另一个构建系统)。

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

此系统的包数据库:http://hackage.haskell.org/

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

在Haskell_98_features和类型学之后,我想你已经可以自己找到并阅读有关它们的文档

顺便说一句,您可能想要测试一些GHC的语言扩展,这可能是未来haskell标准的一部分。

这是我学习haskell最好的方法,希望能对你有所帮助。