Errata


Print Print Icon

Submit your own errata for this product.


The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.


Color Key: Serious Technical Mistake Minor Technical Mistake Language or formatting error Typo Question



Version Location Description Submitted By
Other Digital Version ch01s07

In ePub version, the first code sample is formatted without line breaks:

Is:

ghci> :set +tghci> 'c'
'c'
it :: Char
ghci> "foo"
"foo"
it :: [Char]

Should be:

ghci> :set +t
ghci> 'c'
'c'
it :: Char
ghci> "foo"
"foo"
it :: [Char]


Notes from the Author: I am ill-equipped to test this.

snej 
Safari Books Online ??
3rd block of code in "15.4.1. Supplying Random Numbers"

Error messages about the ambiguous calls. The text indicates the random numbers should be there.

Maciej Piechotka 
Printed Page 8
in the line before the "(e ** pi) - pi" code example

in "we use the(**)" there is a space missing, should read "we use the (**)"

Gabor Greif 
Printed Page 28
1st code sample

"-- file: ch03/add.hs" should be
"-- file: ch02/add.hs" in Chapter 2.

Notes from the Author: It is confusing, but it's a forward reference to a chapter 3 example.

HARUYAMA Seigo 
Printed Page 38
In "Reasoning About Polymorphic Functions"

In the third paragraph it says "nor can it turn an a into a b". While this is correct, it certainly irrelevant for fst. It should probably read "nor can it turn a b into an a", because fst's result type is a.

Gabor Greif 
Printed Page 42
3rd code example from the bottom

Using latest GHC through ubuntu 32 bit system. The type defines the number of the Book type as Int. However, the number is far too large for a 32 bit platform. It will end up wrapping to 494539463. This can be fixed by declaring the types to use Integer rather then Int to make sure it is true on all platforms.

Thomas Tickle 
Printed Page 43
code in "Naming Types and Values

Since we later replace "String" by "ReviewBody" in the next page, it makes more sense to use "Int" in stead of "CustomerID", and have it replaced on the next page as well.

A new comment, in place of the existing one would read:
-- Int is for customer's ID, and String is for the review body

Also, it might be better to reference these "objects" by either their ID number, or by themselves, not both.
Here, each book review holds the entire BookInfo value, but only the ID of the customer (assuming there is a CustomerInfo value as well).
It is a mix of styles.
It would be better if it just held the ID of the BookInfo, or the entire CustomerInfo.

Thanos Tsouanas 
Printed Page 43
1st paragraph

It's rare that a variable name is so non-descriptive that anyone would consider it an error, but in this case the variable name 'cities' is such a poor choice of a variable name in this code:

ghci> let cities = Book 173 "Use of Weapons" ["Iain M. Banks"]

I think it should be considered an error. Naming a Book 'cities' is so out of place that it rattles the reader's confidence in the authors.

It's mentioned again on p. 56 in the 3rd code example.

7stud 
Printed Page 57
first three paragraphs

When the following example, on page 57, is entered, using GHCI, the error message shown below is issued...
A fix to get rid of this error worked but then a subsequent error occurs...see the following once again:

--original code:
-- ch03/Nullable.hs
data Maybe a = Just a
| Nothing

someBool = Just True
--someBool = Main.Just True

someString = Just "somethng"
--someString = Main.Just "somethng"
********************************************************************
if this is loaded -- see following load command and error msg:
ghci>:load ch03/nullable
[1 of 1] Compiling Main ( ch03\nullable.hs, interpreted )

ch03\nullable.hs:5:11:
Ambiguous occurrence `Just'
It could refer to either `Main.Just', defined at ch03\nullable.hs:2:15
or `Prelude.Just', imported from Prelude

ch03\nullable.hs:8:13:
Ambiguous occurrence `Just'
It could refer to either `Main.Just', defined at ch03\nullable.hs:2:15
or `Prelude.Just', imported from Prelude
Failed, modules loaded: none.
ghci>
*********************************************************************
If the following correction is made, the load is successful - however, the example in the third paragraph now fails:
-- ch03/Nullable.hs
data Maybe a = Just a
| Nothing

--someBool = Just True
someBool = Main.Just True

--someString = Just "somethng"
someString = Main.Just "somethng"

**********************************************************************
ghci>:load ch03/nullable
[1 of 1] Compiling Main ( ch03\nullable.hs, interpreted )
Ok, modules loaded: Main.
ghci>
**********************************************************************

Now the following error msg is encountered:
ghci>Just 1.5

<interactive>:1:0:
Ambiguous occurrence `Just'
It could refer to either `Main.Just', defined at ch03\nullable.hs:2:15
or `Prelude.Just', imported from Prelude

patrick lynch 
Printed Page 57
first three paragraphs

When the following example, on page 57, is entered, using GHCI, the error message shown below is issued...
A fix to get rid of this error worked but then a subsequent error occurs...see the following once again:

--original code:
-- ch03/Nullable.hs
data Maybe a = Just a
| Nothing

someBool = Just True
--someBool = Main.Just True

someString = Just "somethng"
--someString = Main.Just "somethng"
********************************************************************
if this is loaded -- see following load command and error msg:
ghci>:load ch03/nullable
[1 of 1] Compiling Main ( ch03\nullable.hs, interpreted )

ch03\nullable.hs:5:11:
Ambiguous occurrence `Just'
It could refer to either `Main.Just', defined at ch03\nullable.hs:2:15
or `Prelude.Just', imported from Prelude

ch03\nullable.hs:8:13:
Ambiguous occurrence `Just'
It could refer to either `Main.Just', defined at ch03\nullable.hs:2:15
or `Prelude.Just', imported from Prelude
Failed, modules loaded: none.
ghci>
*********************************************************************
If the following correction is made, the load is successful - however, the example in the third paragraph now fails:
-- ch03/Nullable.hs
data Maybe a = Just a
| Nothing

--someBool = Just True
someBool = Main.Just True

--someString = Just "somethng"
someString = Main.Just "somethng"

**********************************************************************
ghci>:load ch03/nullable
[1 of 1] Compiling Main ( ch03\nullable.hs, interpreted )
Ok, modules loaded: Main.
ghci>
**********************************************************************

Now the following error msg is encountered:
ghci>Just 1.5

<interactive>:1:0:
Ambiguous occurrence `Just'
It could refer to either `Main.Just', defined at ch03\nullable.hs:2:15
or `Prelude.Just', imported from Prelude

patrick lynch 
Printed Page 62
code example at the top of the page

The code at the top of p. 62 produces the curious result that if you call:

lend 200 201

which is interpreted as: you want to borrow $200 and your current balance is $201, then the result is:

Just 1

which is interpreted as: you were approved for the loan, and your new balance is $1.

On the other hand, if you call

lend 50 99

which means you want to borrow $50 and your current balance is $99, then the result is:

Nothing

which means you were turned down for the loan. Furthermore, if you call

lend 200 150

which means you want to borrow $200 and your current balance is $150, the result is:

Just (-50)

Uhmm...that sounds like the kind of lending that plunged the world's financial system into a crisis.

For anyone starting a bank, they might want to use the following code instead:

lend amount balance = let reserve = 100
newBalance = balance - amount
in

if ***newBalance*** < reserve
then Nothing
else Just newBalance


Also, I think there is a problem with the following sentence, which appears on the bottom of the previous page(p. 61), and which describes the code:

"We meet a money reserve of at least 100, and we return our new balance after subtracting the amount we have loaned:

Should 'meet' be 'need'?








7stud 
Printed Page 63
'The where Clause' section

I ran the example and got the following Load error...

ghci>:load ch03/lending
[1 of 1] Compiling Main ( ch03\lending.hs, interpreted )

ch03\lending.hs:12:4: parse error on input `newBalance'
Failed, modules loaded: none.
*****************************************************************
This is the code:

-- file: ch03/Lending.hs
lend amount balance = let reserve = 100
newBalance = balance - amount
in if balance < reserve
then Nothing
else Just newBalance

lend2 amount balance = if amount < reserve * 0.5
then Just newBalance
else Nothing
where reserve = 100
newBalance = balance - amount
*********************************************************************

patrick lynch 
Printed Page 65
Code example Indentation.hs

I was confused by the comment "we reduce the indentation, so this is a new definition." Eventually I saw what you meant: you are reducing it compared to the "continuation blah" line in firstDefinition. But initially it made no sense, as "continuation yada" has the same indentation as "yada yada", i.e. it's not "reduced" compared to that -- which I think is the most obvious comparison to make.

david.m.carter 
Printed Page 71
start of source code at bottom of page, and similar uses through page 75

I think "Interact.hs" and "./Interact" are intended to be "InteractWith.hs" and "./InteractWith" for consistency or vice versa.

Even better, I think, would be changing these to "Copy.hs" and "./Copy" (or "copy" or even just "cp".) These names provide indication of what the program actually does. It is odd to type "./InteractWith" when copying a file. Also changing to "Copy" would make the naming more parallel with the sensibly named "FixLines" in the next section.

Peter Michaux 
Printed Page 72
3rd code sample

The 3rd code sample uses the executable "./Interact" while it was compiled as "InteractWith" in the 2nd code sample.

Note: on p. 71 the comment in the code sample says
-- file: ch04/InteractWith.hs
-- Save this in a source file, e.g. Interact.hs
which might have to do with the confusion. I'd suggest to drop the second comment line.

Thorsten Seitz 
Printed Page 74
Last line

The second last line reads
"This gives us pre bound to "foo", and suf bound to "bar"."

However, it seems like it should be that "suf" is bound to "\r\nbar" and "rest" is bound to "bar".

Anonymous 
Printed Page 75
1st code sample

"-- file: ch04/SplitLines.hs" should be
"-- file: ch04/FixLines.hs".

HARUYAMA Seigo 
Printed Page 94
middle of page

Here are the two fold examples the text refers to:

foldl (+) 0 (1:2:3:[])
== foldl (+) (0 + 1) (2:3:[])
== foldl (+) ((0 + 1) + 2) (3:[])
== foldl (+) (((0 + 1) + 2) + 3) []
== (((0 + 1) + 2) + 3)

foldr (+) 0 (1:2:3:[])
== 1 + foldr (+) 0 (2:3:[])
== 1 + (2 + foldr (+) 0 (3:[])
== 1 + (2 + (3 + foldr (+) 0 []))
== 1 + (2 + (3 + 0))

The book says on p.94:

-----
The difference between foldl and foldr should be clear from looking at where
the parentheses and the empty list elements show up. With foldl, the empty
list element is on the left, and all the parentheses group to the left.
------

The only empty lists I see in both examples are on the right.

The book continues:

---
With foldr, the zero value is on the right, and the parentheses group to the
right.
----

In the text, 'zero' is bolded to indicate it is a variable name. Presumably, the step function is constantly altering the value of the zero variable, so saying "the" zero value is on the right seems incorrect to me. I think that should read "the initial zero value is on the right".


7stud 
Printed Page 98
4th exercise

asInt_either should have signature

asInt_either :: String -> Either ErrorMessage Int

Gabor Greif 
Printed Page 102
middle

"Partial function application is named currying, ..." I think this is incorrect. Currying and partial function application are different things. It would be good to disentangle them here.

Richard Kelsall 
PDF Page 110
2nd paragraph

"Consider the value (1+2):(3+4):[], If we apply seq to this, it will evaluate the (1+2) thunk."

Not True. It will evaluate the expression as (thunk1 : thunk2). (1+2) is not evaluated, nor is the right thunk.

Further on, the paragraph correctly states that (1+2):(3+4):[] and ((1+2),(3+4)) behave in the same manner when it comes to applying seq, but due to the error above, the following phrase is confusing:

"The same is true for tuples: seq ((1+2), (3+4)) True will do nothing to the thunks inside the pair, since it inmediately hits the pair's constructor."

Alfonso Acosta 
Printed Page 110
2nd paragraph

On page 110, 2nd par it is said that applying seq to (1+2):(3+4):[] will evaluate the (1+2) thunk. This is no correct, as (1+2):(3+4):[] is already in HNF. This can be verified using GHCI:

Prelude> ( (undefined+2) : (3+4) : [] ) `seq` True
True

pepe Gallardo 
Printed Page 111
third paragraph

"value" should be "values"

Peter Michaux 
Printed Page 131
Start of page

The signature proposed in Exercise 1 is a copy of the one proposed in Exercise 1.

J.A.Zaratiegui 
Printed Page 131
1st and 4th paras

Para 1 says "a package contains one library", while para 4 refers to "every library ... in the package". This leaves me confused about whether or not a package can contain more than one library.

david.m.carter 
Printed Page 131
exercise at top of the page

This function probably should be named "nest" instead of "fill".

Gabor Greif 
Printed Page 133
last paragraph in bullet point (1)

After showing how to install packages globally with

$ runghc Setup configure

it goes on to mention that "To install it into our home directory and our personal package database, we must provide a little more information:" but then just moves on to the next step without saying what "more information" is. According to the online version at

http://book.realworldhaskell.org/read/writing-a-library-working-with-json-data.html

the missing command is

$ runghc Setup configure --prefix=$HOME --user

enoksrd 
Printed Page 133
3) at bottom of page

In step 3) the install command is missing. The online version of the book lists the install command as:

$ runghc Setup install

That tries to install in /usr/local so I got the error:

$ runghc Setup install
Installing: /usr/local/lib/mypretty-0.1/ghc-6.8.2
Setup: /usr/local/lib/mypretty-0.1: createDirectory: permission denied (Permission denied)

So I used sudo:

$ sudo runghc Setup install

After installing, you can issue the command

$ ghc-pkg list
/usr/local/lib/ghc-6.8.2/package.conf:
Cabal-1.2.3.0, GLUT-2.1.1.1, HUnit-1.2.0.0, OpenAL-1.3.1.1,
OpenGL-2.2.1.1, QuickCheck-1.1.0.0, array-0.1.0.0, base-3.0.1.0,
bytestring-0.9.0.1, cgi-3001.1.5.1, containers-0.1.0.1,
directory-1.0.0.0, fgl-5.4.1.1, filepath-1.1.0.0, (ghc-6.8.2),
haskell-src-1.0.1.1, haskell98-1.0.1.0, hpc-0.5.0.0, html-1.0.1.1,
mtl-1.1.0.0, mypretty-0.1, network-2.1.0.0, old-locale-1.0.0.0,
old-time-1.0.0.0, packedstring-0.1.0.0, parallel-1.0.0.0,
parsec-2.1.0.0, pretty-1.0.0.0, process-1.0.0.0, random-1.0.0.0,
readline-1.0.1.0, regex-base-0.72.0.1, regex-compat-0.71.0.1,
regex-posix-0.72.0.2, rts-1.0, stm-2.1.1.0,
template-haskell-2.2.0.0, time-1.1.2.0, unix-2.3.0.0,
xhtml-3000.0.2.1

And you should be able to locate your package in there: mypretty-0.1.

Of course, the book doesn't say what installing a package does for you. What good is it? How do you access it?

7stud 
Printed Page 136
Start of "What are typeclasses?"

I would replace "Typeclasses define" with "A typeclass defines". The former could be read by the novice as "Between them, typeclasses define a set of functions..." -- so maybe only one function per typeclass, for all they know.

david.m.carter 
Printed Page 137
4th line from bottom

class name BasicEq is separated as
... Basi
cEq ...

Gabor Greif 
Printed Page 144
Bottom of page

"It allows us to define your own numeric types" -- I don't want _you_ defining _my_ types, thanks very much! (So "us" -> "you"?).

david.m.carter 
Printed Page 149
2nd code example

The comment in the sample indicates that this code will not compile, because CannotShow is not an instance of Show:

data CannotShow = CannotShow
deriving (Show)

-- will not compile, since CannotShow is not an instance of Show
data CannotDeriveShow = CannotDeriveShow CannotShow
deriving (Show)

However, CannotShow *is* an instance of Show, because of the deriving directive. For this code not to compile, the deriving directive of CannotShow should be removed.

Vincent Foley 
Printed Page 149
Example of automatic derivation

The example is incorrect:

data CannotShow = CannotShow
deriving (Show)

-- will not compile, since CannotShow is not an instance of Show
data CannotDeriveShow = CannotDeriveShow CannotShow
deriving (Show)

This will compile nicely, however. I think the deriving (Show) declaration in CannotShow should be removed to correctly illustrate the problem.

David Fries 
Printed Page 198
Last paragraph

"Strig" instead of "String" in the following sentence:
"...followed by any capitalization of the strig .png."

Jeff Heon 
PDF Page 216
4th paragraph

It says
"This means that our attempt to use simpleFind will list directories ending in .c as well as files with the same extension."

But even if you apply (\p -> True)to list all the files, the result of simpleFind actually doesn't contain any directory names. Because for the directory part, it will only recursively list it.

Yi-Fan 
Printed Page 230
second codeblock defining foldTree

The line

let path' = path </> name

in the definition of walk does not append the correct path when traversing down a subdirectory due to the fact that "path" actually holds the value submitted to foldTree.
path should actually be subpath (from the scope of the fold-function).

A quick fix would be:

foldTree ...
where
fold ...
where
walk ...
let path' = subpath </> name

Anonymous 
Printed Page 240
end of 5th para

"the runParser accessor" should be "the runParse accessor"

david.m.carter 
Printed Page 244
1st para of running text

"(==>) lets us chain two Parse values together". From the type signature, it looks as the second is not a Parse value (Parse a) but a function yielding a Parse value (a -> Parse b).

david.m.carter 
Printed Page 253
Beginning of running text

"The (==>&) combinator chains parsers such as (==>), but the righthand side..."

This suggests (==>) is a parser, but it's a combinator. Also "righthand" should be two words. I think this wording is better:

"Like (==>), the (==>&) combinator chains parsers, but unlike (==>), the right hand side..."

david.m.carter 
Printed Page 260
footnote

"We can disregard for now" -- need "this" or "it" after "disregard".

david.m.carter 
Printed Page 266
1st paragraph (or page before)

When talking about HPC, it mentions running "ghc -fhpc Run.hs --make", which works correctly, unless you've compiled the other modules without -fhpc first. A note should be added telling to user to delete all .hi and .o files in the directory. (When these steps are not taken, results like the following are found:

100% expressions used (0/0)
100% boolean coverage (0/0)
100% guards (0/0)
100% 'if' conditions (0/0)
100% qualifiers (0/0)
100% alternatives used (0/0)
100% local declarations used (0/0)
100% top-level declarations used (0/0)

)

Alex Mason 
Printed Page 266
penultimate para of text

"It marked up in bold yellow". Need "is" after "It"; and also, there is no yellow in the printed book, so putting this after "see Figure 11-2" is a little confusing!

david.m.carter 
Printed Page 273
last function defn on page

It looks to me as if this definition of foldA1 will use the first element of "a" twice -- once as the seed ("a ! fst (bounds a)") and once when foldA accesses it as the first member of its copy of a.

david.m.carter 
PDF Page 285
1st paragraph

These two aren't the same as you stated as "evaluated in depth first order."

zip [distance d (scaleToOne ps) | d <- srl] digits
[(distance d (scaleToOne ps), n) | d <- srl, n <- digits]

Yi-Fan 
Printed Page 285
line of code just above "Remembering a Match's Parity"

Surely this list comprehension is going to give you a cross product, not a zip? i.e. of srl and digits both have N elements, the first two expressions on the page will give a list of N pairs, but the third will give a list of N^2 pairs.

david.m.carter 
Printed Page 321
5th paragraph (above 4th code sample)

The sentence "Let's try our the methods of the Monoid typeclass" is wrong.

I believe the author meant "Let's try out the methods" ....

Rodney S 
Printed Page 336
Putting a Few Misconceptions to Rest

There is no explanation for "Monads are for controlling the order of evaluation" while other items have.

Kazu Yamamoto 
Printed Page 336
6th paragraph

For the assertion "Monads are for controlling the order of evaluation" no retort is given.

Frans Slothouber 
Printed Page 337
second paragraph from the bottom

"strictness is under the control of the its implementor." Simple English grammer mistake.

Rodney S 
Printed Page 344
bottom

The example of desugared binding with <- seems to have duplicated text. Specifically, the text

let f pattern = do act2

appears twice, at two levels of indentation. I believe the second appearance is either partially or entirely incorrect.

Chip Salzenberg 
Printed Page 359
First paragraph header

"Golfing Practice: Association Lists"

On page 19 you talk about "duck typing" from Ruby; i.e. you mention a term and define it.

Now you introduce "Golfing" and it is not clear what that has to do with url encoding, alists, or monads. What is "golfing practice" anyway?

On page 369 in the book you have "Another Round of Golf" ... and that does not help to make it clear at all! It's like you are throwing purposefully cryptic headers at the reader.

Rodney S 
PDF Page 361
5th and 6th paragraph

The type of "liftM MovieReview" is not

Maybe (String -> (String -> (String -> MovieReview)))

but

Maybe (String -> Maybe (String -> (String -> MovieReview)))

The result after applying "ap" on the result is not

Maybe (String -> (String -> MovieReview)))

but

Maybe (String -> Maybe (String -> MovieReview)))

ulrivo 
Printed Page 364
in "Rules for working with MonadPlus"

The second rule is given as

-- file: ch15/MonadPlus.hs
v >> == mzero

however, it should be

v >> mzero == mzero

David Fries 
Printed Page 369
top of page

The example runs "(fst . runSupply next) `fmap` randomsIO" twice to demonstrate that different random numbers are supplied each time. Instead, though, it gives on both invocations an error about 'next' being ambiguous, either from Supply or from System.Random. This contradicts the given code which explicitly hides the one from System.Random, so only the one from Supply should be visible.

HairyDude 
Printed Page 375
Last paragraph

"Let's say that we would like guarantee to ourselves that a piece of code ..."

Probably should be "we would like a guarantee" or "we would like to guarantee".

Rodney S 
Printed Page 422
top (first) code excerpt beginning with "$ ghci Regex.hs -lpcre"

The terminal commands for ghci will not work with either the code given up to this point in the chapter or with your sample code from "Examples" on the O'Reilly site for "Real World Haskell". There are numerous omissions and errors. Below is a repaired version of your example Regex.hsc that works with the code excerpt.

{-- snippet headers --}

{-# LANGUAGE CPP, ForeignFunctionInterface #-}



module Regex where



import Foreign

import Foreign.C.Types

import Foreign.C.String

import System.IO.Unsafe

import qualified Data.ByteString.Char8 as DBC



#include <pcre.h>

{-- /snippet headers --}



{-- snippet newtype --}

-- | A type for PCRE compile-time options. These are newtyped CInts,

-- which can be bitwise-or'd together, using '(Data.Bits..|.)'

--

newtype PCREOption = PCREOption { unPCREOption :: CInt }

deriving (Eq,Ord,Show,Read)

{-- /snippet newtype --}



{-- snippet constants --}

-- PCRE compile options

#{enum PCREOption, PCREOption

, caseless = PCRE_CASELESS

, dollar_endonly = PCRE_DOLLAR_ENDONLY

, dotall = PCRE_DOTALL

, dupnames = PCRE_DUPNAMES

, extended = PCRE_EXTENDED

, extra = PCRE_EXTRA

, firstline = PCRE_FIRSTLINE

, multiline = PCRE_MULTILINE

, newline_cr = PCRE_NEWLINE_CR

, newline_crlf = PCRE_NEWLINE_CRLF

, newline_lf = PCRE_NEWLINE_LF

, no_auto_capture = PCRE_NO_AUTO_CAPTURE

, ungreedy = PCRE_UNGREEDY

}

{-- /snippet constants --}



{-- snippet combine --}

-- | Combine a list of options into a single option, using bitwise (.|.)

combineOptions :: [PCREOption] -> PCREOption

combineOptions = PCREOption . foldr ((.|.) . unPCREOption) 0

{-- /snippet combine --}



{-- snippet data --}

data Regex = Regex !(ForeignPtr PCRE)

!DBC.ByteString

deriving (Eq, Ord, Show)

{-- /snippet data --}



{-- snippet unit --}

type PCRE = ()
--The "type PCRE = PCRE (Ptr PCRE)" trick on p.416 is rejected by ghci
{-- /snippet unit --}



{-- snippet pcre_compile --}

foreign import ccall unsafe "pcre.h pcre_compile"

c_pcre_compile :: CString

-> PCREOption

-> Ptr CString

-> Ptr CInt

-> Ptr Word8

-> IO (Ptr PCRE)

{-- /snippet pcre_compile --}



{- snippet compile -}

compile :: DBC.ByteString -> [PCREOption] -> Either String Regex

compile str flags = unsafePerformIO $

DBC.useAsCString str $ \pattern -> do

alloca $ \errptr -> do

alloca $ \erroffset -> do

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 w/ free()

return (Right (Regex reg str))

{- end snippet compile -}

Barney Kendrick 
Printed Page 426
two ghci examples

The "match" executions in the two examples take unnecessary "[]" in the end. For instance,

match r (pack "the quick brown fox") []

should be

match r (pack "the quick brown fox")

There are 5 errors of this in page 426.

Note "RegexFull.hsc" in the online examples should be used instead of "Regex.hsc".

Kazu Yamamoto 
Printed Page 433
towards the bottom of the page

In the section about the ordering of Monad transformers:

"Our transformer stack has IO on the bottom, then StateT, with ReaderT on top. In this particular case, it doesn't matter whether we have ReaderT or WriterT on top, but IO must be on the bottom."

I think WriterT should rather be StateT. WriterT is never used in the following examples.

David Fries 
Printed Page 433
towards the bottom of the page

In the section about the ordering of Monad transformers:

"Our transformer stack has IO on the bottom, then StateT, with ReaderT on top. In this particular case, it doesn't matter whether we have ReaderT or WriterT on top, but IO must be on the bottom."

I think WriterT should rather be StateT. WriterT is never used in the following examples.

David Fries 
Printed Page 441
2nd paragraph from the bottom under "Transformer Stacking Order Is Important"

the paragraph starts "Fromour early examples"

There needs to be a space between "From" and "our"

Rodney S 
Printed Page 454
Note on version 6.10.1 of GHC.

Instead of "It introduces an extensible extension system.", it should read "It introduces an extensible exception system.".

Michel Rijnders 
Printed Page 469
2nd paragraph besides the paw prints

"That could got also be written as ...." I think the "got" should be removed.

Rodney S 
Printed Page 469
2nd paragraph besides the paw prints

"That could got also be written as ...." I think the "got" should be removed.

Rodney S 
Printed Page 472
2nd bullet point.

The typeclasses Enum and bounded are mentioned and we're told to refer ``to "Important Built-in Typeclasses" on page 139'' for more information. However, the section starting on pg 139 doesn't tell us anything about Enum or Bounded (except for briefly mentioning minBound and maxBound in a table). I think those typeclasses are supposed to be explained though, because of pg 472 and because the section following "Important Built-in Typeclasses" starts by mentioning Enum and Bounded among the typeclasses that standard Haskell compilers can automatically derive (pg 148).

enoksrd 
Printed Page 513
2nd paragraph below "Downloading", just above the 'code' section

"We'll be downloading from HTTP servers, so we'll use a Haskell see HTTP library" (....).

we'll use a Haskell see HTTP ... something was truncated there, but what? maybe "so we'll use a Haskell [library called HTTP, so] see HTTP library" ... ??

Rodney S 
Printed Page 548

The force function defined on page 547 does not force the evaluation of the elements in the list it takes. It only evaluates the spine of the list. This can be verified using GHCI as follows:

xs = let ys = [undefined,undefined,undefined]
in force ys `seq` ys

*Main> length xs
3

Hence, evaluating its length can't be used to force the evaluation of random numbers in the input list before the sorting procedure.

The right function to use here in order to avoid the problems described on page 548 is forceList (defined on page 552 of the book).

Pepe Gallardo 
Printed Page 549
3rd paragraph

In order to force the sort to take place, you suggest evaluating the length of the sorted list. That works for the sort functions that you use, but is not a general solution. For instance, calculating the length of a list sorted using the following function does not evaluate its elements:

import List

sort' :: (Ord a) => [a] -> [a]
sort' xs = [ select i xs | i <- [0..length xs-1] ]
where
select 0 xs = minimum xs
select (n+1) xs = select n (delete (select 0 xs) xs)


*Main> sort' [10,9..1]
[1,2,3,4,5,6,7,8,9,10]
*Main> length (sort' [undefined,undefined])
2

I must admit that this is a very inefficient and imperative sort function, but my point is show that the proposed solution is not general enough. Wouldn't it be better to use force as you already do in the generation of the initial list?

Pepe Gallardo 
Printed Page 591
Paragraph below the one at the middle, explaining when to use what hash


There is a typo in the phrase:

Since hashWord32 is the faster of the two hashing functions, we call it if our data is a multiple of 4 bytes in size; otherwise, we call hashLittle2.

'hashWord32' should really be 'hashWord2'

David Fries 
Printed Page 598
2nd para from bottom

"We include -fvia-C here mainly to show how to compile using this option:" (cabal code here....)

The problem is the "cabal code" does not mention "-fvia-C" at all. Perhaps if the line ended in a "." instead of a ":", the one could interpret the line meaning "the above paragraph mentions -fvia-C for completeness." But the ":" drives one to look at the next text and then not finding "-fvia-C" is confusing.

Rodney S 
Printed Page 604
para just below the long code listing

"Out timed action ensures that a value is evaluated ...."

Should be "Our timed action ...".

Rodney S 
PDF Page 625
6th paragraph

The function removeInv doesn't remove an item from a list.

The following similar function does it:

removeInv :: Eq a => a -> [a] -> Maybe [a]
removeInv x xs =
case span (/= x) xs of
(zs,(_:ys)) -> Just $ zs++ys
(_,[]) -> Nothing

ulrivo 
Printed Page 628
last para under "Choosing Between Alternatives" header

the sentence:
"If sellItem fail, orelse will invoke the return False action, causing our sale function to return immediately."

You give the orElse type signature, but no use of it and no "return False" application or even a "sellItem" application for that matter. I think you are missing something like this:

sellItem Banjo 42 steveMartin slimPickens `orElse` return False

otherwise the assertion "will invoke the return False action" does not make sense. What "return False" action?

Rodney S 


"...this book will expand your mind. It will give you a new way of thinking about the whole enterprise of programming: when you have worked through these pages, you'll write better code in your current favourite language."
--Simon Peyton Jones, Microsoft Research, Haskell language architect and designer of the Glasgow Haskell Compiler