现实世界 Haskell 的哪些部分现在已经过时或被认为是不好的做法?

问题描述:

Real World Haskell 的第 19 章中,由于 Control.Exception 的更改,许多示例现在都失败了.

In the chapter 19 of Real World Haskell a lot of the examples now fail due to the change of Control.Exception.

这让我觉得这本书中的一些东西实际上已经过时了,不值得再学习了,毕竟已经 6 年了.我唯一的其他参考是Learn You aHaskell For Great Good,虽然它是一本好书,但与 RWH 相比,它的基础要简单得多.

That makes me think maybe some of the stuff in this book is actually obsolete and not worth studying anymore, after all it's been 6 years. My only other reference is Learn You a Haskell For Great Good, though it's a great book, it's much more basic compared with RWH.

之前读过这本书的任何人都可以就其中的哪些部分不再相关提供一些建议吗?尤其是本书后半部分的章节,例如软件事务内存、并发编程、套接字编程等.

Can anyone who have read the book before please give some advice on which parts of it are no longer relevant? Especially the chapters in the second half of the book, for example, software transactional memory, concurrent programming, socket programming, etc.

这是关于 2008 年 12 月出版的这本书的版本,这是迄今为止(2017 年 11 月)唯一已知的版本

This is about the edition of the book that's published on Dec 2008, which is the only known edition as of today (Nov 2017)

RWH的主要问题

它太旧了. RWH 是在使用 GHC 6.8 版时编写的.6.8使用基本版本 3.0.xx6.10.1 已经使用了 4.0.0.0,其中引入了 许多变化.这只是从 6.8 到 6.10 的跳跃.GHC 的当前版本是 7.10.单子已经改变.目前有一个讨论 return 中删除 >Monad,所以现实世界 Haskell 中的 Monad 实例将真正与现实世界不同步.

Main issue of RWH

It's old. RWH was written at a time version 6.8 of GHC was being used. 6.8 used base version 3.0.x.x. 6.10.1 already used 4.0.0.0, which introduced many changes. And that's just the jump from 6.8 to 6.10. The current version of GHC is 7.10. Monads have been changed. There's currently a discussion to remove return from Monad, so the Monad instance in Real World Haskell will really be out of sync with the real world.

话虽如此,它仍然是通用指南的有用资源.但请记住,自发布以来,许多库都发生了变化.

That being said, it's still a useful resource for general guidelines. But keep in mind that many libraries changed since its release.

您可以在阅读 RWH 的同时阅读斯蒂芬·迪尔 (Stephen Diehl) 的我希望在学习 Haskell 时知道什么".它提供了额外的洞察力,但请注意,有些部分对新手并不友好.

Something you can read along while reading RWH is "What I Wish I Knew When Learning Haskell" by Stephen Diehl. It provides additional insight, but be aware, some sections aren't really newcomer friendly.

  • 阅读评论.它们通常包含给定段落/部分是否仍然相关和/或有效的信息.
  • 阅读您要使用的库/函数的文档.即使你很懒惰,也至少要知道类型.

这只是我在阅读 RWH 时注意到的一些事情的快速概述.可能不完整.

This is just a quick overview of some of the things that I noticed while reading RWH. It's probably incomplete.

自 GHC 7.10 以来.

null的类型>更改 由于 Foldable-Traversable-Proposal.许多其他函数,例如 foldrfoldl 和许多其他以前只为 Prelude 中的 [a] 定义的函数> 已替换为更通用的 Foldable t =>t a 变体.

The type of null has been changed due to the Foldable-Traversable-Proposal. Many other functions such as foldr, foldl and many other that were previously only defined for [a] in the Prelude have been replaced with more general Foldable t => t a variants.

自 Haskell 平台 2010 年或 2008 年底以来.

尽管在 脚注中提到了这一点>,QuickCheck 库从版本 1 到版本 2 在很多方面发生了变化.例如,generate 现在使用 Gen a 而不是 StdGen,旧的 generate 的功能在 Test.QuickCheck.Gen.unGen 中.

Although this is mentioned in a footnote, the QuickCheck library has changed in many ways from version 1 to version 2. For example, generate now uses Gen a instead of StdGen, and the functionality of the old generate is in Test.QuickCheck.Gen.unGen.

如有疑问,请查看文档.

从 GHC 7.10 开始,Applicative 现在是 Monad 的超类,这是 2007 年没有计划的.

As of GHC 7.10, Applicative is now a superclass of Monad, something that wasn't planned in 2007.

在 GHC 7.10 中,Applicative 将成为 Monad 的超类,可能会破坏很多用户代码.为了缓解这种转变,GHC 现在在定义与 Applicative-Monad 提案(AMP).

In GHC 7.10, Applicative will become a superclass of Monad, potentially breaking a lot of user code. To ease this transition, GHC now generates warnings when definitions conflict with the Applicative-Monad Proposal (AMP).

参见 7.8.1发行说明.

请站起来真实状态的monad好吗?部分,作者声称

为了定义一个 Monad 实例,我们必须提供一个合适的类型构造函数以及 (>>=)return 的定义代码>.这就引出了State的真正定义.

In order to define a Monad instance, we have to provide a proper type constructor as well as definitions for (>>=) and return. This leads us to the real definition of State.

-- file: ch14/State.hs
newtype State s a = State
    runState :: s -> (a, s)
}

那不再是真的,因为 State 和它的朋友现在是通过

That's no longer true, because State and its friends are now implemented via

type State  s = StateT  s Identity
type Writer w = WriterT w Identity
type Reader r = ReaderT r Identity

所以它们是由它们的 monad 转换器定义的.

So they're defined by their monad transformer.

整个章节都很好,但可以在评论或 Yuras Shumovich 的博客,以下代码中的终结器部分是不好的做法:

The overall chapter is fine, but as one can read in the comments or on Yuras Shumovich's blog, the finalizer part in the following code is bad practise:

pcre_ptr <- c_pcre_compile pattern (combineOptions flags) errptr erroffset nullPtr
if pcre_ptr == nullPtr
    then do
        err <- peekCString =<< peek errptr
        return (Left err)
    else do
        reg <- newForeignPtr finalizerFree pcre_ptr -- release with free()
        return (Right (Regex reg str))

因为 malloc() 应该与 free()newdelete 一起使用使用deallocate分配,应该总是使用正确的函数.

As malloc() should be used with free(), new with delete, allocate with deallocate, one should always use the correct function.

TL;DR 您应该始终使用为您分配内存的相同分配器来释放内存.

TL;DR You should always free memory with the same allocator that allocated it for you.

如果外部函数分配内存,您还应该使用随附的释放函数.

If a foreign function allocates memory, you should also use the accompanying deallocation function.

错误处理从 6.8 到 6.10 完全改变了,但你已经注意到了.最好阅读文档.

Error handling changed completely from 6.8 to 6.10, but you noticed that already. Better read the documentation.

某些示例似乎已损坏.此外,还有其他可用的 HTTP 库.

Some of the example seem to be broken. Also, there are other HTTP libraries available.

一般分析技术仍然相同,并且示例(见下文)是一个很好的案例研究,可以解决您的程序中可能出现的问题.但是 RWH 缺少多线程分析,例如通过 ThreadScope.此外,据我所知,整本书都没有关注惰性 IO.

General profiling techniques are still the same, and the example (see below) is a great case study for problems that can occur in your program. But RWH is missing multi-threaded profiling, e.g. via ThreadScope. Also, lazy IO isn't concerned throughout the whole book, as far as I know.

mean :: [Double] -> Double
mean xs = sum xs / fromIntegral (length xs)

第 24 章 &第28章(并发和并行编程&STM)

虽然 第 24 章并发和多核编程第 28 章软件事务内存 仍然相关,Simon Marlow 的书 Haskell 中的并行和并发编程 仅关注并发和并行编程,并且是最近的(2013).RWH 中完全没有 GPU 编程和修复.

Chapter 24 & Chapter 28 (Concurrent and parallel programming & STM)

While Chapter 24. Concurrent and multicore programming and Chapter 28. Software transactional memory are still relevant, Simon Marlow's book Parallel and Concurrent Programming in Haskell focuses solely on concurrent and parallel programming and is pretty recent (2013). GPU programming and repa are completely missing in RWH.

与其他章节一样,设计库的一般指南仍然写得很好且相关.但是,由于ST的一些变化(?),结果无法再编译.

As with the other chapters, the general guidelines of the design library is still well written and relevant. However, due to some changes (?) concerning ST, the result cannot be compiled anymore.

它仍然主要是最新的.毕竟,网络编程并没有那么容易改变.但是,代码使用了不推荐使用的函数 bindSocketsClose,它们应该被替换为 bindclose(最好通过合格进口).请记住,它是非常低级的,您可能需要使用更专业的高级库.

It's still mostly up to date. After all, network programming doesn't change so easily. However, the code uses deprecated functions bindSocket and sClose, which should be replaced by bind and close (preferably via qualified import). Keep in mind that it's very low-level, you might want to use a more specialized high-level library.

GHC 6.8 是引入 Haskell 平台之前的最后一个版本.因此,附录告诉您手动获取GHC和Cabal.别.相反,请按照 haskell.org 下载页面上的说明进行操作.

GHC 6.8 was the last version before the Haskell Platform has been introduced. Therefore, the appendix tells you to get GHC and Cabal by hand. Don't. Instead, follow the instructions on the haskell.org download page.

另外,附录没有告诉你关于 Cabal 沙箱,它是在 Cabal 1.18 让你摆脱依赖地狱.当然,stack 完全丢失了.

Also, the appendix doesn't tell you about Cabal sandboxes, which were introduced in Cabal 1.18 and free you from dependency hell. And of course, stack is missing completely.

有些主题根本没有在 RWH 中讨论.这包括流媒体库,例如 pipesconduit,还有镜头.

Some topics are not discussed in RWH at all. This includes streaming libraries such as pipes and conduit, and also lenses.

针对这些主题提供了多种资源,但这里有一些介绍链接,可让您了解它们的内容.此外,如果您想使用向量,请使用 vectors 包.

There are several resources out there for those topics, but here are some links to introductions to give you an idea what they're about. Also, if you want to use vectors, use the vectors package.

RWH 在几个地方使用了 Control.Applicative(<$>),但没有解释 Control.Applicative根本.LYAHTypeclassopedia 包含关于 Applicative 的部分.鉴于 ApplicativeMonad 的超类(见上文),建议认真学习该类.

RWH uses Control.Applicative's (<$>) at several points, but doesn't explain Control.Applicative at all. LYAH and the Typeclassopedia contain sections on Applicative. Given that Applicative is a superclass of Monad (see above), it's recommended to learn that class by heart.

此外,Control.Applicative(以及类型类本身)的几个运算符现在是 Prelude 的一部分,因此请确保您的运算符不会与 、 等.

Furthermore, several operators of Control.Applicative (and the typeclass itself) are now part of the Prelude, so make sure that your operators don't clash with <$>, <*> and others.

  • Conduit Overview by Michael Snoyman (author of conduit)
  • Pipes tutorial by Gabriel Gonzales (author of pipes, included in the pipes package)
  • Cabal 1.18 版,其中引入了沙箱
  • stack,一个跨平台的程序用于开发 Haskell 项目
  • ghc-mod,vim 的后端,emacs、Sublime Text 等编辑器
  • 运行时类型多态性(:i ($) 发生了巨大变化)
  • -XTypeInType
  • -XDataKinds莉>
  • -XGADT
  • -XRankNTypes
  • -XGenericNewtypeDeriving
  • -XDeriveFunctor
  • 6.6 之后发生的任何其他扩展