haskell - 开始使用 Haskell

标签 haskell functional-programming

这个问题的答案是community effort .编辑现有答案以改进这篇文章。它目前不接受新的答案或互动。








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

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

最佳答案

我将根据您在 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 principles , 和 Programming in Haskell .它们每章都带有练习,所以你有一些简单的小问题,与你在最后几页学到的东西相匹配。
要尝试的问题的一个很好的列表是 haskell 99 problems page .这些从非常基本的开始,随着您的进行而变得更加困难。做很多这些是非常好的练习,因为它们可以让您练习递归和高阶函数的技能。我建议跳过任何需要随机性的问题,因为这在 Haskell 中有点困难。查询 this SO question如果您想使用 QuickCheck 测试您的解决方案(请参阅下面的中级)。
一旦你完成了其中的一些,你就可以继续做一些 Project Euler问题。这些按完成的人数排序,这是一个相当好的难度指示。这些比之前的问题更能测试你的逻辑和 Haskell,但你应该仍然可以做前几个。 Haskell 解决这些问题的一大优势是整数不受大小限制。为了完成其中的一些问题,阅读第 7 章和第 8 章学习 Haskell 会很有用。
初学者
在那之后,你应该对递归和高阶函数有相当好的掌握,所以现在是开始解决一些更现实世界问题的好时机。一个很好的起点是 Real World Haskell (在线书籍,您也可以购买纸质版)。我发现前几章对于以前从未进行过函数式编程/使用递归的人来说介绍得太快了。但是,通过您在之前的问题中所获得的练习,您应该会发现它完全可以理解。
解决本书中的问题是学习如何在 Haskell 中管理抽象和构建可重用组件的好方法。这对于习惯于面向对象 (oo) 编程的人来说至关重要,因为普通的 oo 抽象方法(oo 类)不会出现在 Haskell 中(Haskell 有类型类,但它们与 oo 类非常不同,更像是 oo 接口(interface))。我不认为跳过章节是一个好主意,因为每个章节都引入了很多在后面章节中使用的新想法。
一段时间后,您将进入第 14 章,即可怕的 monad 章节 (dum dum dummmm)。由于概念太抽象,几乎所有学习 Haskell 的人都难以理解 monad。我想不出另一种语言中的任何概念像函数式编程中的 monad 一样抽象。 Monads 允许将许多想法(例如 IO 操作、可能失败的计算、解析等)统一到一个想法下。因此,如果您在阅读了 monad 章节后还没有真正理解它们,请不要气馁。我发现阅读许多关于 monad 的不同解释很有用;每个人都对这个问题提出了新的看法。这是一个很好的list of monad tutorials .我强烈推荐 All About Monads ,但其他的也不错。
此外,概念真正融入需要一段时间。这来自使用,也来自时间。我发现有时在一个问题上 sleep 比什么都重要!最终,这个想法会被点击,你会想知道为什么你很难理解一个实际上非常简单的概念。当这种情况发生时真是太棒了,当它发生时,您可能会发现 Haskell 是您最喜欢的命令式编程语言 :)
为了确保您完全理解 Haskell 类型系统,您应该尝试解决 20 intermediate haskell exercises .这些练习使用有趣的函数名称,例如“furry”和“banana”,如果您还没有的话,可以帮助您很好地理解一些基本的函数式编程概念。用一堆布满箭头、 unicorn 、香肠和毛茸茸的香蕉的纸来度过你的夜晚的好方法。
中级
一旦你理解了 Monads,我认为你已经从一个初学者 Haskell 程序员过渡到一个中级 Haskell 程序员。那么从这里去哪里呢?我要推荐的第一件事(如果您还没有从学习 monad 中学到它们)是各种类型的 monad,例如 Reader、Writer 和 State。同样,Real world Haskell 和 All about monads 对此进行了大量报道。要完成您的 monad 培训,必须学习有关 monad 转换器的知识。这些使您可以将不同类型的 Monad(例如 Reader 和 State monad)合二为一。一开始这似乎没什么用,但是在使用它们一段时间后,您会想知道没有它们您是如何生活的。
现在,如果您愿意,您可以完成现实世界的 Haskell 书籍。现在跳过章节并不重要,只要你有单子(monad)。只需选择您感兴趣的内容即可。
凭借您现在拥有的知识,您应该能够使用 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 是了解这些高级概念以及它们如何组合在一起的一个很好的概述。 .
  • 适用:类似于 Monads 的接口(interface),但功能较弱。每个 Monad 都是 Applicative,但反之则不然。这很有用,因为有些类型是 Applicative 但不是 Monad。此外,使用 Applicative 函数编写的代码通常比使用 Monad 函数编写等效代码更具组合性。见 Functors, Applicative Functors and Monoids从学习你的 Haskell 指南。
  • Foldable , Traversable :抽象列表的许多操作的类型类,以便相同的功能可以应用于其他容器类型。另见 haskell wiki explanation .
  • Monoid : Monoid 是一种具有零(或 mempty)值和操作的类型,记为 <>将两个幺半群连接在一起,使得 x <> mempty = mempty <> x = xx <> (y <> z) = (x <> y) <> z .这些被称为恒等律和结合律。很多类型都是幺半群,比如数字,有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 年开始!),但从这里我猜你开始写博士论文,新的 ghc 扩展,并提出新的抽象。
    获取帮助
    最后,在学习的任何阶段,都有多个获取信息的地方。这些是:
  • #haskell irc channel
  • mailing lists .这些值得注册只是为了阅读发生的讨论 - 有些非常有趣。
  • haskell.org 主页上列出的其他地方

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

    关于haskell - 开始使用 Haskell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1012573/

    相关文章:

    docker - 为Haskel Web应用程序构建Docker镜像的最佳实践是什么

    haskell - 多次调用 applyTwice 时无法理解结果

    scala - 如何推理 Scala Cats/fs2 中的堆栈安全?

    list - Haskell:从列表中一一打印 Int

    Haskell : words, unwords 分隔符

    haskell - 如何在加速示例包的示例上启用 CUDA?

    functional-programming - 函数式编程中的大数据结构

    scala - Scala 中类方法和闭包上下文中的纯函数

    javascript - 这段代码的流程是怎样的?

    algorithm - 我是否可以始终将仅可变算法转换为单赋值并且仍然有效?