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

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


试着用它写一些简单的程序。

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

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

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

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


这里有一本好书,你可以在线阅读:Real World Haskell

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

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


我的一些同事有很好的学习Haskell的经验!

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

在这里也检查一下答案


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


我建议加入#haskell irc频道并在那里提问。我就是这样学会哈斯克尔的。如果你像上面建议的那样使用Real World Haskell,实时回答你的问题会有很大帮助。许多聪明的人在#haskell上写haskell是为了好玩和盈利,所以你会得到很多好的输入。试一试!


我建议你首先从阅读BONUS教程开始,然后阅读Real World Haskell(在线免费)。加入#Haskell IRC频道,在irc.freenode.com上,并提出问题。这些人对新手都很友好,而且在过去的时间里帮了我很多。此外,在这里,在SO是一个伟大的地方,以获得帮助,你不能掌握的东西!试着不要气馁,一旦成功,你的想法就会被震撼。

奖金'教程将为您准备,并让您为真实世界哈斯克尔带来的惊险刺激做好准备。祝你好运!


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

绝对的初学者

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

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

一些学习Haskell基础知识的好指南是Happy Learn Haskell Tutorial和Learn You a Haskell for Great good(或其JupyterLab的改编版)的前6章。在阅读这些文章的同时,用你所知道的知识来解决一些简单的问题也是一个很好的主意。

另外两个很好的资源是Haskell Programming from first principles和Programming in Haskell。它们每一章都有练习,所以你有一些小的简单的问题来匹配你在前几页学到的东西。

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

Once you have done a few of those, you could move on to doing a few of the Project Euler problems. These are sorted by how many people have completed them, which is a fairly good indication of difficulty. These test your logic and Haskell more than the previous problems, but you should still be able to do the first few. A big advantage Haskell has with these problems is Integers aren't limited in size. To complete some of these problems, it will be useful to have read chapters 7 and 8 of learn you a Haskell as well.

初学者

After that you should have a fairly good handle on recursion and higher order functions, so it would be a good time to start doing some more real world problems. A very good place to start is Real World Haskell (online book, you can also purchase a hard copy). I found the first few chapters introduced too much too quickly for someone who has never done functional programming/used recursion before. However with the practice you would have had from doing the previous problems you should find it perfectly understandable.

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

After a while you will get to chapter 14, the dreaded monads chapter (dum dum dummmm). Almost everyone who learns Haskell has trouble understanding monads, due to how abstract the concept is. I can't think of any concept in another language that is as abstract as monads are in functional programming. Monads allows many ideas (such as IO operations, computations that might fail, parsing,...) to be unified under one idea. So don't feel discouraged if after reading the monads chapter you don't really understand them. I found it useful to read many different explanations of monads; each one gives a new perspective on the problem. Here is a very good list of monad tutorials. I highly recommend the All About Monads, but the others are also good.

此外,要真正理解这些概念也需要一段时间。这来自于使用,也来自于时间。我发现有时候把问题睡一觉比什么都有用!最终,你会明白你为什么要努力去理解一个在现实中非常简单的概念。当这种情况发生时,它是非常棒的,当它发生时,你可能会发现Haskell是你最喜欢的命令式编程语言:)

为了确保你完全理解Haskell类型系统,你应该尝试解决20个中级Haskell练习。这些练习使用了有趣的函数名称,如“furry”和“banana”,如果你还没有掌握一些基本的函数编程概念,可以帮助你很好地理解它们。在一堆写满箭,独角兽,香肠和毛茸茸的香蕉的纸上度过你的夜晚真不错。

中间

Once you understand Monads, I think you have made the transition from a beginner Haskell programmer to an intermediate haskeller. So where to go from here? The first thing I would recommend (if you haven't already learnt them from learning monads) is the various types of monads, such as Reader, Writer and State. Again, Real world Haskell and All about monads gives great coverage of this. To complete your monad training learning about monad transformers is a must. These let you combine different types of Monads (such as a Reader and State monad) into one. This may seem useless to begin with, but after using them for a while you will wonder how you lived without them.

如果你愿意,现在你可以完成现实世界哈斯克尔的书。跳过章节现在真的不重要,只要你有单子下来。选择你感兴趣的就可以了。

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

Parsec: for parsing programs and text. Much better than using regexps. Excellent documentation, also has a real world Haskell chapter. QuickCheck: A very cool testing program. What you do is write a predicate that should always be true (eg length (reverse lst) == length lst). You then pass the predicate the QuickCheck, and it will generate a lot of random values (in this case lists) and test that the predicate is true for all results. See also the online manual. HUnit: Unit testing in Haskell. gtk2hs: The most popular gui framework for Haskell, lets you write gtk applications. happstack: A web development framework for Haskell. Doesn't use databases, instead a data type store. Pretty good docs (other popular frameworks would be snap and yesod).

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

Applicative: An interface like Monads, but less powerful. Every Monad is Applicative, but not vice versa. This is useful as there are some types that are Applicative but are not Monads. Also, code written using the Applicative functions is often more composable than writing the equivalent code using the Monad functions. See Functors, Applicative Functors and Monoids from the learn you a haskell guide. Foldable,Traversable: Typeclasses that abstract many of the operations of lists, so that the same functions can be applied to other container types. See also the haskell wiki explanation. Monoid: A Monoid is a type that has a zero (or mempty) value, and an operation, notated <> that joins two Monoids together, such that x <> mempty = mempty <> x = x and x <> (y <> z) = (x <> y) <> z. These are called identity and associativity laws. Many types are Monoids, such as numbers, with mempty = 0 and <> = +. This is useful in many situations. Arrows: Arrows are a way of representing computations that take an input and return an output. A function is the most basic type of arrow, but there are many other types. The library also has many very useful functions for manipulating arrows - they are very useful even if only used with plain old Haskell functions. Arrays: the various mutable/immutable arrays in Haskell. ST Monad: lets you write code with a mutable state that runs very quickly, while still remaining pure outside the monad. See the link for more details. FRP: Functional Reactive Programming, a new, experimental way of writing code that handles events, triggers, inputs and outputs (such as a gui). I don't know much about this though. Paul Hudak's talk about yampa is a good start.

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

多参数类型类/函数依赖关系 类型的家庭 存在量化的类型 幻类型 GADTS 其他人……

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

最后,您将希望更多地了解各种Haskell工具。这些包括:

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

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

专家

你将花费数年时间到达这个阶段(从2009年开始!),但我猜你从这里开始写博士论文,新的ghc扩展,并提出新的抽象概念。

得到帮助

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

#haskell irc频道 邮件列表。仅仅为了阅读其中的讨论就值得报名参加——有些非常有趣。 haskell.org主页上列出的其他地方

结论

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


为了补充别人的答案——有一个有用的答案会在编码时帮助你(例如在解决项目欧拉问题时): Hoogle。可以使用命令行界面,也可以使用web界面。

命令行

在你安装了Haskell平台之后,一定要在cabal上安装hoogle

Hoogle用法示例:

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

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

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

是的,你需要的函数已经存在了,它叫做iterate。你可以通过迭代func 5来使用它!

Web界面

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


Graham Hutton的《Programming in Haskell》简明扼要,相当透彻,而且他多年的Haskell教学经验也很好地说明了这一点。这几乎总是我建议人们开始的时候,不管你从哪里开始。

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

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


如果您只有命令式/OO语言的经验,我建议使用更传统的函数式语言作为垫脚石。Haskell是非常不同的,你必须理解很多不同的概念。我建议先使用ml风格的语言(比如f#)。


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

我建议您访问Haskell页面:http://haskell.org。这里有很多材料,还有很多Haskell中最新的东西的引用,这些都是Haskell社区批准的。


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

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


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

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

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

Haskell专家的智慧有两个关键: 了解类型。 获得对每个类型类及其与其他类型类之间关系的深刻直觉 类型类,通过熟悉许多示例来支持。

Monad Reader本身对于函数式程序员(不仅仅是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(libraryDB), Cabal(构建系统),darcs(另一个构建系统)。

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

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

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

在Haskell_98_features和Typeclassopedia之后,我认为您已经可以自己找到并阅读有关它们的文档

顺便说一下,你可能想要测试一些GHC的语言扩展,这些扩展将来可能会成为haskell标准的一部分。

这是我学习haskell最好的方法。我希望它能帮助你。