一句吐槽 . 一道勘误 . 一些点评 $ Haskell趣学指南
本来想写详细点,但是表达能力有限,就短说吧XD。
举的例子都非常的好,对functor,monad的切入也很不错。不过我学完后还是什么都写不出来的感觉(我自己的问题)。作者的这本书更像书博客系列,可读性强,不枯燥,但是涉及面太少了。比如我试着像作者一样写monad,但是编译器却报错,后来我查了一下才知道要写monad的instance,得先让其成为Functor, Applicative的实例,而写monoid的实例,得先成为Semigroup的实例。作者没有提及,所以学的时候遇到好多的问题。还有作者没有涉及标准库,所以我对haskell的标准库结构缺乏一个感性认识,如果去看标准库文件,里面的一大堆操作符有点恐怖!可能作者写作本意就如此,他希望读者是对这门语言有个感性认识并专注于函数式思维,而不是专注于编程的细节之中。
读这本书最大的收获是新思维方式吧,想问题的解答之前先思考输入是什么输出是什么,把接口定义好(成为Functor、Applicative、Monad的实例),再去实作。不过不知道这算不算是函数式编程中的样板代码呢?
后面的内容虽好,但是作者在一些问题上给出的答案都是给人“看起来是这个结果”的感觉。一些看起来很直观的问题其实一点也不直观,如果仔细写出那些Monad的计算过程其实是很复杂的,至少对初学者来说是这样。作者这种“想当然”还是会犯错,下面我更正一个错误。
在Chapter 13中“The State Monad”段落前的最后一段代码是错的:
最左边的是原文的代码(其实不是的,我多加了一个“pop”)。原文的代码是错误的,因为它的结果总是do结构最后的那个“pop”产生的结果。因为先“push”一次,再“pop”两次——其结果就好像“pop”一次那样,这正好掩盖了错误。如果你在后面加任意个“push”和“pop”的组合,并让最后一个动作是“pop”,你会发现结果总是一样。我故意加了一个“pop”,你可以验证他跟原文的代码产生一样的结果。 中间的代码是翻译过来的代码,大致是这样,你可以了解到为什么它总是最后一个“pop”的结果。(关于do实际等价的代码可以参考这里:Haskell/do notation。如果中间代码并不完全等价于左边,请告诉我)。 最右边的代码是实现了正确语义的代码。
最后想吐槽一下函数式编程,以前看过一个比较有名但有争议的人写的文章,说monad那种东西不过是函数式语言的缺陷造成的,因为没很好的地方保存数据,所以通过monad来将这些数据穿过去达到目的(我不记得他是否只是吐槽haskell本身)。通过这本书了解一些之后觉得还是蛮有道理的,不过学到的思维是好的。