协慌网

登录 贡献 社区

Haskell 入门

几天后,我试图围绕 Haskell 中的函数式编程范例。我通过阅读教程和观看截屏视频来完成这项工作,但似乎没有什么能够坚持下去。现在,在学习各种命令式 / OO 语言(如 C,Java,PHP)时,练习对我来说是个好方法。但由于我不知道 Haskell 能够做什么,并且因为有许多新概念可供使用,我还不知道从哪里开始。

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

答案

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

绝对的菜鸟

首先,Haskell 能够胜任任何事情,具备足够的技能。它非常快(在我的经验中只支持 C 和 C ++),可用于从模拟到服务器,guis 和 Web 应用程序的任何事情。

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

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

另外两个好的资源是来自第一原理的 Haskell 编程Haskell 中的编程 。他们都为每一章都附带练习,所以你有一些小问题与你在最后几页学到的东西相匹配。

要尝试的一个很好的问题列表是haskell 99 问题页面 。这些开始非常基础,并且随着你的继续变得更加困难。这很好的做法很多,因为它们让你练习递归和高阶函数的技能。我建议跳过任何需要随机性的问题,因为在 Haskell 中这有点困难。如果您想使用 QuickCheck 测试解决方案,请查看此问题 (请参阅下面的中间版 )。

一旦你完成了其中的一些,你就可以继续做一些Project Euler问题。这些是根据完成它们的人数排序的,这是一个相当好的困难迹象。这些测试你的逻辑和 Haskell 比以前的问题更多,但你仍然应该能够做到前几个。 Haskell 对这些问题的一个很大的优势是整数的大小不受限制。要完成其中的一些问题,阅读第 7 章和第 8 章将了解 Haskell 是很有用的。

初学者

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

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

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

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

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

中间

一旦你理解了 Monads,我认为你已经从初学者 Haskell 程序员转变为中级 haskeller。那么从哪里开始呢?我建议的第一件事(如果你还没有从学习 monad 中学到它们)是各种类型的 monad,例如 Reader,Writer 和 State。再一次,真实世界的 Haskell 和 All about monads 给出了很好的报道。要完成你的 monad 训练,学习 monad 变形金刚是必须的。这些允许您将不同类型的 Monad(例如 Reader 和 State monad)组合成一个。这可能看起来没用,但是在使用它们一段时间之后你会想知道没有它们你是如何生活的。

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

凭借您现在拥有的知识,您应该能够使用 cabal 上的大多数软件包(至少是文档中的软件包),以及 Haskell 附带的大多数库。要尝试的有趣库列表如下:

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

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

  • HUnit :Haskell 中的单元测试。

  • gtk2hs :Haskell 最流行的 gui 框架,允许你在 Haskell 中编写 gtk 应用程序。

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

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

  • 适用:像 Monads 这样的界面,但功能较弱。每个 Monad 都是适用的,但反之亦然。这很有用,因为有些类型是 Applicative 但不是 Monads。此外,使用 Applicative 函数编写的代码通常比使用 Monad 函数编写等效代码更具组合性。请参阅学习哈克尔指南中的Functors,Applicative Functors 和 Monoids

  • 可折叠 ,可遍历 :抽象列表的许多操作的类型类,以便相同的函数可以应用于其他容器类型。另请参阅haskell wiki 说明

  • Monoid :Monoid 是一个具有零(或 mempty)值的类型,以及一个将两个 Monoid 连接在一起的带符号<>的操作,这样x <> mempty = mempty <> x = xx <> (y <> z) = (x <> y) <> z 。这些被称为身份和相关性法律。许多类型都是mempty = 0 ,例如数字, mempty = 0<> = + 。这在许多情况下都很有用。

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

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

  • ST Monad :允许你编写一个运行速度非常快的可变状态的代码,同时在 monad 之外仍保持纯粹。请参阅链接查看更多细节。

  • FRP:功能反应编程,一种编写处理事件,触发器,输入和输出(例如 gui)的代码的新的实验方法。我对此并不了解。 Paul Hudak 关于 yampa 的谈话是一个好的开始。

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

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

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

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

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

在学习所有这些新库和概念的同时,在 Haskell 中编写一个中等大小的项目非常有用。它可以是任何东西(例如小游戏,数据分析器,网站, 编译器 )。通过这项工作,您可以应用许多您正在学习的内容。你可以长时间呆在这个级别(这就是我所处的位置)。

专家

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

获得帮助

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

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

结论

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

我的一些同事在学习你是一个很好的 Haskell 时有很好的经验

该教程针对的是那些具有命令式编程语言经验但之前没有使用函数式语言编程的人。

并在这里检查答案

这是一本很好的书,你可以在网上阅读: 真实世界 Haskell

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

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