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

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


当前回答

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

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

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

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

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

其他回答

我将根据你在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而得到了提高,因为我看到了许多抽象思想的新方法。

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

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

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

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

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