关于函数式编程:Haskell入门

Getting started with Haskell

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

那么,你是怎么学哈斯克尔的?是什么让你真正"打破僵局"?还有,有什么好的开始练习的主意吗?


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

绝对初学者好的。

首先,哈斯克尔有能力做任何事,有足够的技能。它非常快(仅靠C和C++在我的经验中),并且可以用于从模拟到服务器、GUI和Web应用的任何东西。好的。

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

首先,学习haskell基础知识的一些好指南是快乐学习haskell教程和学习你的haskell的前6章。在阅读这些文章的同时,用你所知道的来解决简单的问题也是一个很好的主意。好的。

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

要尝试的问题列表是haskell 99问题页面。这些都是从非常基础开始的,并且随着你的继续而变得更加困难。做很多这样的工作是很好的实践,因为它们可以让你在递归和高阶函数中练习你的技能。我建议跳过任何需要随机性的问题,因为这在Haskell中有点困难。检查这个问题,以防你想用快速检查测试你的解决方案(见下面的中间部分)。好的。

一旦你做了其中的一些,你可以继续做一些项目欧拉问题。这些是根据完成这些任务的人数来排序的,这是一个相当好的困难迹象。这些测试你的逻辑和哈斯克尔比以前的问题,但你仍然应该能够做的前几个。Haskell在这些问题上的一个巨大优势是整数的大小不受限制。为了完成其中的一些问题,阅读第7章和第8章也会很有用。好的。

初学者好的。

在这之后,您应该对递归和高阶函数有一个相当好的处理,所以现在是开始处理更多现实世界问题的好时机。一个很好的开始是现实世界哈斯克尔(在线图书,你也可以购买一份硬拷贝)。我发现前几章介绍得太快了,对于以前从未做过函数式编程/使用递归的人来说。然而,通过练习,你会发现你以前的问题是完全可以理解的。好的。

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

过一段时间,你将进入第14章,可怕的蒙娜斯章(dum dummm)。几乎每个学习哈斯克尔的人都很难理解单子,因为单子的概念是多么抽象。在另一种语言中,我想不出任何概念像函数式编程中的monads那样抽象。monads允许在一个想法下统一许多想法(例如IO操作、可能失败的计算、解析…)。所以,如果读完蒙纳兹的章节后,你不真正理解它们,不要感到气馁。我发现阅读许多不同的单子解释是很有用的;每一个都对这个问题给出了一个新的观点。这里有一个非常好的单子教程列表。我强烈推荐所有关于单子的,但是其他的也很好。好的。

而且,这些概念还需要一段时间才能真正融入其中。这是通过使用,也是通过时间。我发现有时候在问题上睡觉比其他任何事情都更有帮助!最终,这个想法会被点击,你会好奇为什么你努力理解一个在现实中非常简单的概念。当这种情况发生时,它是可怕的,当它发生时,您可能会发现haskell是您最喜欢的命令式编程语言:)好的。

为了确保你完全理解哈斯克尔式系统,你应该尝试解决20个中间哈斯克尔练习。这些练习使用一些有趣的函数名,如"furry"和"banana",如果您还没有基本的函数编程概念,可以帮助您很好地理解它们。用一堆纸包着箭、独角兽、香肠和毛茸茸的香蕉度过夜晚的好方法。好的。

中间的好的。

一旦你理解了Monads,我认为你已经从一个初学者Haskell程序员过渡到了一个中级的Haskeller。那么从这里到哪里呢?我推荐的第一件事(如果你还没有从学习单子中学到它们)是各种类型的单子,比如读者、作家和国家。同样,现实世界中的哈斯克尔和所有关于蒙纳兹的报道都对此进行了大量报道。要完成Monad培训,必须学习Monad Transformers。这些允许您将不同类型的monad(如读卡器和状态monad)组合为一个。一开始这似乎没用,但用了一段时间后,你会想知道没有它们你是怎么生活的。好的。

现在你可以完成现实世界的哈斯克尔书,如果你想。现在跳过章节并不重要,只要你有单子轻拍。选择你感兴趣的。好的。

有了现在的知识,您应该能够使用cabal上的大多数包(至少有文档记录的包…)以及haskell附带的大多数库。要尝试的有趣库列表如下:好的。

  • 用于分析程序和文本。比使用regexps好多了。优秀的文档,也有一个现实世界的哈斯克尔章。好的。

  • 快速检查:一个非常酷的测试程序。您要做的是编写一个应该始终为真的谓词(例如length (reverse lst) == length lst)。然后将谓词传递给quickcheck,它将生成大量随机值(在本例中是列表),并测试谓词对于所有结果是否为真。另请参阅联机手册。好的。

  • Hunit:Haskell的单元测试。好的。

  • gtk2hs:haskell最流行的GUI框架,允许您用haskell编写gtk应用程序。好的。

  • happstack:haskell的Web开发框架。不使用数据库,而是使用数据类型存储。相当好的文档(其他流行的框架是snap和yesod)。好的。

此外,还有许多概念(如monad概念)您最终应该学习。这将比第一次学习单子更容易,因为你的大脑将习惯于处理所涉及的抽象层次。对于学习这些高级概念以及它们如何结合在一起的一个很好的概述是typeclassopedia。好的。

  • 实用性:像Monads这样的界面,但功能较弱。每一个单子都是适用的,但反之亦然。这是有用的,因为有一些类型是适用的,但不是单子。此外,使用应用函数编写的代码通常比使用monad函数编写等效代码更容易组合。请参阅《学习你的哈斯克尔指南》中的函数、应用函数和单倍体。好的。

  • 可折叠的、可遍历的:类型类,它抽象了列表的许多操作,以便相同的函数可以应用于其他容器类型。另请参见haskell wiki解释。好的。

  • monoid:monoid是一个具有零(或mempty)值的类型,并且是一个将两个monoid连接在一起的操作,未标记<>,这样x <> mempty = mempty <> x = xx <> (y <> z) = (x <> y) <> z。这些被称为同一性和关联性定律。许多类型都是单体,如数字,带有mempty = 0<> = +。这在许多情况下都很有用。好的。

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

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

  • 圣莫纳德:让你写一个可变状态的代码,运行非常快,但仍然保持纯粹的蒙纳德之外。有关详细信息,请参阅链接。好的。

  • 功能反应式编程,一种新的、实验性的代码编写方法,用于处理事件、触发器、输入和输出(如GUI)。不过,我对此知之甚少。保罗·哈达克谈论亚姆巴是个好的开始。好的。

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

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

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

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

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

在学习所有这些新的库和概念的同时,在Haskell编写一个中等规模的项目是非常有用的。它可以是任何东西(例如小游戏、数据分析仪、网站、编译器)。在这方面的工作将允许你应用你现在所学的许多东西。你在这个水平上呆了很长时间(这就是我所处的位置)。好的。

专家好的。

你要花上好几年才能到达这个阶段(2009年的你好!)但是从这里我猜你开始写博士论文,新的GHC扩展,并提出新的摘要。好的。

得到帮助好的。

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

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

结论好的。

结果比我想象的要长…不管怎样,我认为精通哈斯克尔是个好主意。这需要很长的时间,但这主要是因为你正在学习一种全新的思维方式。学习Java并不像学习Ruby那样,但是在学习C.之后,就像学习Java一样,我发现我的面向对象编程技能由于学习Haskell而有所改进,因为我看到了许多抽象思想的新方法。好的。好啊。


我的一些同事有很好的经验,学习你的哈斯克尔非常好!.

Tutorial aimed at people who have
experience in imperative programming
languages but haven't programmed in a
functional language before.

并检查这里的答案


这是一本你可以在网上阅读的好书:现实世界哈斯克尔

我所做的大多数Haskell程序都是为了解决项目Euler问题。

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


我很喜欢看这13集关于使用haskell进行功能性编程的系列剧。

C9讲座:Erik Meijer博士-功能编程基础:http://channel9.msdn.com/show/going+deep/repeat-series-erik-meijer-functional-programming-fundamentals-chapter-1/


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

命令行

安装好haskell平台后,务必使用cabal install hoogle

hoogle用法示例:

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

如果使用f 5a -> (a -> a) -> [a],如果使用5 f,则该函数将为(a -> a) -> a -> [a]类型(我们假定该函数用于一般类型,而不仅仅是Int)。

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

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

网页界面

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


格雷厄姆·赫顿在哈斯克尔的编程简明扼要,相当透彻,他教授哈斯克尔的几年的经验也确实证明了这一点。这几乎总是我建议人们从哪里开始,不管你从那里去哪里。

特别是,第8章("函数解析器")提供了开始处理monad所需的实际基础工作,我认为到目前为止是最好的开始的地方,其次是所有关于monad的内容。(不过,关于这一章,请注意网站上的勘误表:没有特别的帮助,您不能使用do表格。您可能想先了解typeclass,然后自己解决这个问题。)

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


不要试图用有趣的隐喻来阅读所有的单子教程。他们只会让你更糟。


我建议加入哈斯克尔IRC频道,在那里提问。这就是我学习哈斯克尔的方法。如果你像上面提到的那样经历真实世界的话,实时回答你的问题会有很大帮助。很多聪明人在haskell上写haskell是为了好玩和赚钱,所以你会得到很多好的投入。试试看!


这些是我最喜欢的

haskell:函数式编程

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

真实世界的Haskell

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

我还可以推荐另一个haskell教程作为介绍。

另一个很好的学习资源(可能在中级水平上),它帮助了我很多,在我所看到的其他答案中没有提到,是布伦特·约基的typeclassopedia,它可以在monad阅读器中找到(第13期)。

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

There are two keys to an expert Haskell hacker’s wisdom:

  • Understand the types.

  • Gain a deep intuition for each type class and its relationship to other
    type classes, backed up by familiarity with many examples.

  • Monad阅读器本身对于函数式程序员(不仅仅是Haskell程序员)来说是一个绝对的宝库。


    我认为通过实例来实现haskell的特性是最好的开始方法。

    http://en.wikipedia.org/wiki/haskell_98_功能

    这里有一些复杂的类型类,包括monad和arrows

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

    对于现实世界中的问题和更大的项目,请记住这些标签:ghc(最常用的编译器)、hackage(librarydb)、cabal(构建系统)、darcs(另一个构建系统)。

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

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

    GHC编译器的维基:http://www.haskell.org/haskell wiki/ghc

    在haskell_98_特性和typeclassopedia之后,我想你已经可以自己找到并阅读关于它们的文档了。

    顺便说一下,您可能想测试一些GHC的语言扩展,这可能是将来Haskell标准的一部分。

    这是我学习哈斯克尔的最好方法。我希望它能帮助你。


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

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

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

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

    在那之后,阅读很多高级概念(monad、arrows、io、递归数据结构),因为haskell是无限的,并且有很多高级概念。


    我建议你先从阅读Bonus的教程开始,然后阅读现实世界的haskell(免费在线)。加入irc.freenode.com上的haskell irc频道,并提问。这些人对新手非常友好,而且随着时间的推移帮助了我很多。而且,就在这里,这是一个很好的地方来获得帮助的事情,你无法掌握!尽量不要泄气,一旦它发出咔嗒声,你的思想就会被打乱。

    奖金的教程将使你精力充沛,并让你为现实世界哈斯克尔带来的刺激之旅做好准备。祝你好运!


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


    第一个答案是非常好的。为了达到专家水平,你应该和一些专家一起攻读博士学位。

    我建议您访问haskell页面:http://haskell.org。在那里,你有很多材料,和许多参考最新的东西在哈斯克尔,由哈斯克尔社区批准的哈斯克尔。