Which parts of Real World Haskell are now obsolete or considered bad practice?
In the chapter 19 of Real World Haskell a lot of the examples now fail due to the change of Control.Exception
.
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.
EDIT: 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)
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.xx 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.
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.
General remarks
Remarks to chapters
This is just a quick overview of some of the things that I noticed while reading RWH. It's probably incomplete.
Chapter 2. Types and Functions vs the FTP
Since GHC 7.10.
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 => ta
variants.
Chapter 11. Testing and quality assurance
Since Haskell-platform 2010 or late 2008.
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
.
In doubt, check the documentation.
Chapter 14. Monads & Chapter 15. Programming with monads
Code breaking: Applicative m => Monad m
As of GHC 7.10, Applicative
is now a superclass of Monad
, something that wasn't planned in 2007.
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).
See 7.8.1 release notes.
The State
/ Writer
/ Reader
monads
In the Will the real state monad please stand up? section, the authors claim
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)
}
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
So they're defined by their monad transformer.
Chapter 17. Interfacing with C: the FFI
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))
As malloc()
should be used with free()
, new
with delete
, allocate
with deallocate
, one should always use the correct function.
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.
Chapter 19. Error handling
Error handling changed completely from 6.8 to 6.10, but you noticed that already. Better read the documentation.
Chapter 22. Extended Example: Web Client Programming
Some of the example seem to be broken. Also, there are other HTTP libraries available.
Chapter 25. Profiling and optimization
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, eg 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)
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.
Chapter 26. Advanced library design: building a Bloom filter
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.
Chapter 27. Network programming
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.
Appendix A. Installing GHC and Haskell libraries
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.
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.
Missing content
Some topics are not discussed in RWH at all. This includes streaming libraries such as pipes and conduit, and also lenses.
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.
Control.Applicative
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.
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.
Lenses
lens
) Streaming libraries
conduit
) pipes
, included in the pipes
package) Tooling
stack
, a cross-platform program for developing Haskell projects ghc-mod
, a backend for vim, emacs, Sublime Text and other editors New/missing language extensions and GHC changes
:i ($)
has changed tremendously) -XTypeInType
-XDataKinds
-XGADT
-XRankNTypes
-XGenericNewtypeDeriving
-XDeriveFunctor
上一篇: Haskell声明中的惊叹号是什么意思?