【问题标题】:Getting started with Haskell开始使用 Haskell
【发布时间】:2010-11-03 23:55:30
【问题描述】:

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

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

【问题讨论】:

标签: haskell functional-programming


【解决方案1】:

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

绝对初学者

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

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

一些学习 Haskell 基础知识的好指南是 Happy Learn Haskell TutorialLearn You a Haskell for Great Good 的前 6 章(或其 JupyterLab adaptation)。在阅读这些内容的同时,用你所知道的知识解决简单的问题是一个非常好的主意。

另外两个不错的资源是Haskell Programming from first principlesProgramming in Haskell。它们都附有每一章的练习,所以你有一些与你在最后几页学到的东西相匹配的小问题。

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

一旦你完成了其中的一些,你就可以继续做一些Project Euler 的问题。这些是按完成它们的人数排序的,这是一个相当好的难度指示。这些比以前的问题更能测试你的逻辑和 Haskell,但你应该仍然能够完成前几个问题。 Haskell 解决这些问题的一大优势是整数不受大小限制。要完成其中一些问题,阅读第 7 章和第 8 章的学习 Haskell 会很有帮助。

初学者

在那之后,您应该对递归和高阶函数有相当好的处理能力,所以现在是开始处理一些更现实世界的问题的好时机。一个很好的起点是Real World Haskell(在线书籍,也可以购买纸质版)。对于以前从未做过函数式编程/使用过递归的人来说,我发现前几章介绍得太快了。但是,通过练习之前的问题,您应该会发现它完全可以理解。

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

一段时间后,您将进入第 14 章,可怕的单子章节 (dum dum dummmm)。几乎每个学习 Haskell 的人都很难理解 monad,因为这个概念非常抽象。我想不出另一种语言中的任何概念与函数式编程中的 monad 一样抽象。 Monads 允许将许多想法(例如 IO 操作、可能失败的计算、解析……)统一在一个想法下。因此,如果您在阅读了 monads 章节后并没有真正理解它们,请不要灰心。我发现阅读对 monad 的许多不同解释很有用。每个人都对问题提出了新的看法。这是一个非常好的list of monad tutorials。我强烈推荐All About Monads,但其他的也不错。

此外,这些概念需要一段时间才能真正融入其中。这既来自于使用,也来自于时间。我发现有时在问题上睡觉比其他任何事情都更有帮助!最终,这个想法会成功,你会想知道为什么你很难理解一个实际上非常简单的概念。当这种情况发生时真是太棒了,当它发生时,你可能会发现 Haskell 是你最喜欢的命令式编程语言 :)

为确保您完全理解 Haskell 类型系统,您应该尝试解决 20 intermediate haskell exercises。这些练习使用有趣的函数名称,如“furry”和“banana”,可以帮助您很好地理解一些基本的函数式编程概念(如果您还没有这些概念)。用一堆写满箭头、独角兽、香肠和毛茸茸的香蕉的纸来度过一个美好的夜晚。

中级

一旦你理解了 Monads,我认为你已经从一个初级 Haskell 程序员转变为一个中级 Haskell 程序员。那么从这里去哪里呢?我要推荐的第一件事(如果你还没有从学习 monad 中学到它们)是各种类型的 monad,例如 Reader、Writer 和 State。再一次,真实世界的 Haskell 和 All about monads 对此进行了很好的报道。要完成你的 monad 训练,学习 monad 转换器是必须的。这些让您可以将不同类型的 Monad(例如 Reader 和 State monad)组合成一个。刚开始这似乎没什么用,但在使用它们一段时间后,您会想知道没有它们您将如何生活。

现在,您可以根据需要完成真实世界的 Haskell 书籍。现在跳过章节并不重要,只要你有 monads down pat。只需选择您感兴趣的内容即可。

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

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

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

  • HUnit:Haskell 中的单元测试。

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

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

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

  • Applicative:类似于 Monads 的接口,但功能较弱。每个 Monad 都是 Applicative,但反之则不然。这很有用,因为有些类型是 Applicative 但不是 Monad。此外,使用 Applicative 函数编写的代码通常比使用 Monad 函数编写等效代码更具可组合性。请参阅Learn you a haskell 指南中的Functors, Applicative Functors and Monoids

  • Foldable,Traversable:将列表的许多操作抽象化的类型类,以便将相同的功能应用于其他容器类型。另请参阅haskell wiki explanation

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

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

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

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

  • FRP:Functional Reactive Programming,一种新的实验性代码编写方式,用于处理事件、触发器、输入和输出(例如 gui)。不过我对此了解不多。 Paul Hudak's talk about yampa 是一个好的开始。

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

  • 多参数类型类/功能依赖项
  • 类型族
  • 存在量化类型
  • 幻影类型
  • GADTS
  • 其他...

很多 Haskell 都是基于 category theory,所以你可能想研究一下。一个好的起点是Category Theory for Computer Scientist。如果不想买书,作者相关article也不错。

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

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

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

专家

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

获得帮助

最后,在任何学习阶段,都有多个地方可以获取信息。它们是:

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

结论

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

【讨论】:

  • 耶箭头!首先你让单子塑造你的大脑,然后你站在你的头上思考共单子,然后你同时做这两个以获得箭头:) Haskell中有很多表达能力可以用类型级别打开编程也是。
  • @nanothief Monad 更强大,但组合性也更弱……很多人使用 monad 可以摆脱更干净的Applicative 代码。大多数Functors 也是Monads,但是当fmap 就足够时,你不要到处使用>>=return,因为如果你可以使用后者会导致更简单的代码.
  • @pelotom,我添加了 typeclassopedia 链接以及在该部分使用 Applicative 的更好理由,并删除了 Functor 部分。由于大多数教材(包括 RWH)都强调 Monad,因此很难以正确的顺序获得 Monad 和 Applicative 概念。另一方面,自从我最初写答案(将近 2 年:O)以来,教你一个 Haskell 教程已经走了很长一段路,并且在 Monad 之前教 Applicative,也许现在应该是推荐的学习 Haskell 的方式。
  • 很好的建议。我是一年多前开始的,现在大部分时间都在中级阶段。反馈:RWH 的 monad 章节(第 14 章)解释得很差。阅读 RWH 的在线版本是有益的,因为它包含有助于本章的众包 cmets。 FWIW,You Could Have Invented Monads,是最适合我的 monad 教程。
  • @tomf:谢谢!我一直对这个答案的表现感到惊讶——我写它已经快五年了,但它仍然很强大。不过,我需要尽快对其进行更新,因为它有点过时了。它没有提到镜头、管道、约束类型、haskell 平台、类型级别数字,而且自从撰写本文以来,它们都是相当重要的新主题。你是对的,RWH 不再那么好了,它已经很长时间没有更新了,而且很多示例都没有编译。很高兴它仍然对你有帮助。
【解决方案2】:

我还可以推荐Yet Another Haskell Tutorial作为介绍。

另一个很好的学习资源(可能是中级水平),对我有很大帮助,据我所知,其他答案中没有提到,是 Brent Yorgey 的 Typeclassopedia,可以在The Monad Reader (Issue 13)

中找到

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

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

  1. 了解类型。

  2. 深入了解每种类型及其与其他类型的关系 类型类,以熟悉许多示例为后盾。

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

【讨论】:

    【解决方案3】:

    Graham Hutton 的 Programming in Haskell 简洁、相当透彻,他多年教 Haskell 的经验也很明显。无论您从哪里开始,我几乎总是建议人们从这里开始。

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

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

    【讨论】:

    • 这是一本完全被低估的书(和答案)。关于函数式解析器的一章,然后是关于 IO 的一章,甚至都没有提到 monad,这确实是一种优雅的教学方法。
    【解决方案4】:

    添加其他人的答案 - 在编码时(例如在解决项目欧拉问题时)有一个有用的方法可以帮助您: 胡歌。您可以使用命令行界面或web interface

    命令行

    安装 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

    网页界面

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

    【讨论】:

    • 一旦您了解了如何向 Hoogle 询问您需要什么,找到您需要的标准库函数就会变得非常容易。
    【解决方案5】:

    这些是我最喜欢的

    Haskell: Functional Programming with Types

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

    Real World Haskell

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

    【讨论】:

      【解决方案6】:

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

      我建议你访问 Haskell 页面:http://haskell.org。那里有很多材料,以及很多对 Haskell 中最新内容的引用,并且得到了 Haskell 社区的认可。

      【讨论】:

      • 对不起,但在这里使用博士论点就像说你必须有一把 300 美元的菜刀才能成为一名好厨师。即使是哈斯克尔之父西蒙·佩顿·琼斯(Simon Peyton Jones)也没有博士学位。实践和坚持是在这里和任何其他领域获得专业知识的原因。
      【解决方案7】:

      我确实认为通过示例来实现 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 编译器的维基:http://www.haskell.org/haskellwiki/GHC

      在 Haskell_98_features 和 Typeclassopedia 之后,我想你已经可以自己找到并阅读关于它们的文档了

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

      这是我学习 Haskell 的最佳方式。希望对你有帮助。

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          【解决方案9】:

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

          【讨论】:

          • Elm 可能是这些替代品中最接近、更有用且对初学者友好的...
          • 我不同意通过 F# 等临时路线经过。对我来说,这就像喝伏特加,你必须快速啜饮。那样更痛苦,但也有快乐。临时路线,只会给我带来更多的困惑。
          【解决方案10】:

          我建议你先阅读BONUS' tutorial,然后阅读Real World Haskell (online for free)。加入#Haskell IRC channel, on irc.freenode.com,并提出问题。这些人对新手绝对友好,并且随着时间的推移帮助了我很多。此外,就在 SO 上,这里是获得您无法掌握的事情帮助的好地方!尽量不要气馁,一旦点击,你的想法就会被震撼。

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

          【讨论】:

            【解决方案11】:

            我建议加入#haskell irc channel 并在那里提问。这就是我学习 Haskell 的方式。如果您按照上面的建议通过 Real World Haskell,实时回答您的问题将大有帮助。 #haskell 上的很多聪明人写 Haskell 是为了好玩和赚钱,所以你会得到很多好的意见。试试看!

            【讨论】:

            • +1 - 明确一点:不要不要通过 irc 频道学习它只是。比如,不要进去问“我如何编写一个 haskell 程序?如何添加数字?”
            • 除了 irc freenode 之外,最近 Discord 聊天中也有越来越多关于 haskell 的热烈讨论。
            【解决方案12】:

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

            【讨论】:

            • 同意!请参阅“抽象、直觉和“monad 教程谬误””:byorgey.wordpress.com/2009/01/12/…
            • 我也同意了!但是,如果您想尝试一下,this video 是一个非常好的第一步。它接近关于 Java 编程的 monad,通常使人们更舒服。
            【解决方案13】:

            我的一些同事对Learn You a Haskell for Great Good! 有很好的体验。

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

            也检查here的答案

            【讨论】:

            • 我支持这个。另外,由于不是很明显,这里有一个可下载的 pdf 版本教程的链接:learnyouahaskell.com/learnyouahaskell.pdf 网页设计很棒,但我也喜欢地铁的副本。
            • 我是从这个开始的,但我的意见是你应该直接去 Real World Haskell。区别就像从 K&R 学习 C 或“C for dummies”,它试图简单,但它的方法错过了重要的东西。我认为最好直接弄清事实,而不是试图以“必要的方式”学习 Haskell。
            • 我非常喜欢这个,我在这个和 Real World Haskell 上投入了很多时间。 IMO,“Learn You a Haskell”比真实世界的 Haskell 提供了更深入的洞察力,尽管它们都是很好的资源。
            • @abababa22 我认为先读 LYAH 然后再去 RWH 是最好的主意。 LYAH 不只是教你 Haskell;它教你函数式编程。当你解决问题时,你开始以实用的方式思考。显然,仅 LYAH 不足以编写大型应用程序,但它会以正确的方式改变您的想法。如果您来自命令式背景,这是最好的方法,IMO
            • @Telemachus 请注意:PDF 不是最终版本,至少缺少最后一章。
            【解决方案14】:

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

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

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

            【讨论】:

            • 根据我的经验,真实世界的 Haskell 非常棒,直到你到达第 5 章。从那时起我不会推荐它。
            • 为什么选择@MasterMastic?第 5 章之后的问题是什么?在我花钱之前我想知道。
            • @JayBlanchard 在第 5 章中,您开始获得一个库的具体示例,这很好,但他们告诉您他们将要做什么,去做,但他们没有完全解释为什么,一点都不清楚,而且有相当多的魔法十六进制文字。你只是在走过场。这对我来说不是最大的问题,最大的问题是这本书在很大程度上依赖于那些硬而长的例子(足够长到超过一整章)。你几乎不能只阅读你想要的部分。我认为伟大的作者,惊人的知识,但非常执行力很差。
            【解决方案15】:

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

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

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

            在我解决了十几个之后,我打破了僵局:)

            之后,阅读大量高级概念(Monads、Arrows、IO、递归数据结构),因为 Haskell 是无限的,而且数量很多。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-11-10
              • 2020-03-18
              • 2016-09-04
              • 2015-02-05
              相关资源
              最近更新 更多