Errata

Real World Haskell

Errata for Real World Haskell

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 Note Update

Version Location Description Submitted by Date submitted
??
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  Apr 14, 2009 
Printed Page Index
Index

Consider adding the word "composition" to the index. Also, "function composition" should be added (or "composition" as a sub topic under "functions".) These should probably point to page 105, "Code Reuse Through Composition".

Mike Depot  Apr 17, 2010 
Other Digital Version ch8.5
Under globToRegex' definition

Our first clause stipulates that if we hit the end of our
glob pattern (by which time we'll be looking at the empty
string), we return $, the regular expression symbol for
"match end-of-line."

Not true. The "first clause" returns the empty string, not "$". That maybe the way it was originally but refactored the "$" into the PARENT or CALLING function (the non-prime globToRegex).

Anonymous  Oct 06, 2010 
Other Digital Version ch24
ch24/Sorting.hs

The parSort method is parenthesized incorrectly. The version given works, but does not gain any speed from parallelism (which is the topic of this chapter). Where the code has

force greater `par` (force lesser `pseq` (lesser ++ x:greater))

it should have:

((force greater) `par` (force lesser)) `pseq` (lesser ++ x:greater)

The corrected version forces both halves to be sorted before the concatenation.

Peter Drake  May 21, 2014 
Printed Page 28
add.hs example after the 1st paragraph

The comment is
-- file: ch03/add.hs

But actually, the example is given in chapter 2.
And I think the comment should be "-- file: ch02/add.hs"

Hongzhi Song  Feb 07, 2014 
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  Apr 12, 2009 
Printed Page 41
code definition of BookInfo and examples using it on page 42

The data definition of BookInfo uses type Int which is not able to represent the 13 digit ISBN number used in the example on page 42 (as least on 32 bit machines):

ghci> 9780135072455 :: Int
494539463

Type Integer should have been used.

Steve Pretty  Feb 27, 2011 
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  Jun 18, 2009 
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  Jan 11, 2009 
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  Feb 28, 2009 
Printed Page 49
1st block of code

Definition of struct vector is missing in C code.

Should add:

struct vector {
double a;
double b;
}

zolli  Apr 16, 2010 
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  Aug 27, 2009 
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  Aug 27, 2009 
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  Aug 28, 2009 
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  Apr 09, 2009 
ePub Page 66
4th paragraph

"Even though the number of elements and their types is the same," should read "Even though the number of elements and their types are the same,"

John Claus  Apr 28, 2015 
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  Jul 05, 2009 
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  Jan 04, 2009 
Printed Page 72
3rd paragraph

On Windows PCs the following differences were noted:
[note: $./Interact should be InteractWith - this was noted in a separate errata - this occurs in two places].
1. ./Interact should simply be
Interact [or more correctly InteractWith]
2. ./Interact hello-in.txt hello-out.txt should simply be
Interact hello-in.txt hello-out.txt
3. cat hello-in.txt should be type hello-in.txt
4. cat hello-out.txt should be type hello-out.txt
[note: cat is not a valid PC DOS command].

patrick lynch  Jan 24, 2011 
Printed Page 72
3rd paragraph

On Windows PCs the following differences were noted:
[note: $./Interact should be InteractWith - this was noted in a separate errata - this occurs in two places].
1. ./Interact should simply be
Interact [or more correctly InteractWith]
2. ./Interact hello-in.txt hello-out.txt should simply be
Interact hello-in.txt hello-out.txt
3. cat hello-in.txt should be type hello-in.txt
4. cat hello-out.txt should be type hello-out.txt
[note: cat is not a valid PC DOS command].

patrick lynch  Jan 24, 2011 
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  Dec 24, 2008 
PDF Page 88
1st line

"square on the remainder of the empty list." should be "square on the remainder of the nonempty list."

Anonymous  Jan 01, 2011 
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  Mar 14, 2009 
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  Apr 12, 2009 
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  Jan 05, 2009 
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  Mar 30, 2009 
Printed Page 111
third paragraph

The already published errata is wrong.

the plural of "type of value" is "types of value", not "types of values", so the book is right in the first place.

Enrico Maria De Angelis  May 03, 2020 
PDF Page 115
2nd line

The first non-commented line of file ch05/Main.hs should be

module Main where

Anonymous  Feb 10, 2012 
Printed Page 115
second line from the top

module Main () where

should be

module Main (main) where

or at least

module Main where

Enrico Maria De Angelis  Apr 30, 2020 
Printed Page 119
several

Page 119 says that module Prettify will contain "text", "double", and "string" functions (line after first code block; line 5 in last para before second code block; and the signatures in the second code block itself).

However, it seems function "string" does not belong in Prettify. Page 120-122 shows in great detail how to write a function named "string" in module PrettyJSON. The function described is rather JSON-specific, so that makes more sense. Furthermore, the import list from Prettify on page 124 does not mention any function "string".

Marcus Uneson  Mar 08, 2010 
Printed Page 130
3rd para, line 2

The values of width and col are 0 and 2, respectively ->

The values of width and col are 2 and 0, respectively

Marcus Uneson  Mar 08, 2010 
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  Jan 01, 2009 
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  Apr 09, 2009 
Printed Page 131
exercise at top of the page

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

Gabor Greif  Jun 18, 2009 
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  Feb 05, 2009 
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  Mar 27, 2009 
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  Apr 11, 2009 
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  Dec 14, 2008 
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  Feb 05, 2009 
Printed Page 149
Sample

you have data
CannotShow = CannotShow deriving (Show);

This is supposed to be lacking "deriving (Show)"

This means CannotDeriveShow's CannotShow is deriving show -- and subsequently, it does compile, even though the book says explicitly it won't compile.

Evan Carroll  Jan 25, 2010 
Printed Page 149
3rd lin of 2nd code block

The 3rd line should be removed because compile error doesn't occur.

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 149
Second Code Example -- ch06/AutomaticDerivation.hs

The example reads:

data CannotShow = CannotShow
deriving (Show)

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

However, because of the first 'deriving (Show)', it is in fact the case that CannotShow is an instance of Show, and therefore CannotDeriveShow can in fact derive Show with no problem.

It appears that the first 'deriving (Show)' was left in unintentionally.

Kyle Pointer  Jun 09, 2015 
Printed Page 150
1st line of middle paragraph

Because Haskell doesn't natively support lists that contain types of
different values,

should be

Because Haskell doesn't natively support lists that contain values of
different types,

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 153
1st code block

FlexibleInstances language extension is required to compile this code.
We will get following errors without this extension.

Illegal instance declaration for `JSON [(String, a)]'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are type variables,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `JSON [(String, a)]'

Therefore, we recommend to add a footnote to the sentence above the code
sample.

You have to add the FlexibleInstances language extension.

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 153
code sample of ch06

This code also needs FlexibleInstances language extension.

? file: ch06/Overlap.hs
class Borked a where
bork :: a -> String

should be

? file: ch06/Overlap.hs
{}
class Borked a where
bork :: a -> String

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 159
2nd code example

? file: ch06/JSONClassExport.hs

should be&#65306;
? file: ch06/JSONClass.hs

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 159
2nd code example in sidebar

? file: ch06/JSONClassExport.hs

should be

? file: ch06/JSONClass.hs

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 160
Penultimate paragraph

Taking this and wrapping it to become a JAry JValue is just a matter of
applying the newtype?s type constructor:

should be

Taking this and wrapping it to become a JAry JValue is just a matter of
applying the newtype?s data constructor:

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 160
Last paragraph

To turn this into a JValue, we apply another type constructor:

should be

To turn this into a JValue, we apply another data constructor:

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 175/176
example

While trying one of the examples I found an error due to a change in GHC. The example on pages 175/176 uses System.IO.Error.catch which has been replaced by System.IO.Error.catchIOError.

Anonymous  Jun 09, 2014 
Printed Page 179
1st paragraph 3rd line

It's a pure function since it has no side effects
and always returns the same result each time it is called.

should be

It's a pure function since it has no side effects
and always returns the same result each time it is called
with the same string.

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 199
8th sample

This is only an addendum to errata already confirmed.

8th sample might be written as follows:

ghci> getAllTextMatches("I, B. Ionsonii, uurit a lift'd batch" =~ "(uu|ii)":: (AllTextMatches [] String))
["ii","uu"]

Really verbose, isn't it?

Juan Antonio Zaratiegui Vallecillo  May 12, 2010 
Printed Page 203
First line after code block

The line says "Our first clause stipulates that if we hit the end of the glob pattern (...) we return $".

It is not true that the first clause of globToRegex' stipulates that. It is a consequence of globToRegex on page 202, which calls globToRegex'. Although it is clear what you mean, the sentence needs to be reformulated.

Jan van Mansum  Feb 14, 2010 
Printed Page 213
bottom of page, example ch09/RecursiveContents.hs

if you try to run this example on a Windows PC, using backslashes in the directory ['\'] name it will be interpreted as an escape character...see following:

getRecursiveContents "C:\Users\User\Downloads\rwh-examples2\examples\ch09"

gives the following error message:
<interactive>:1:25:
lexical error in string/character literal at character 'U'

if run with forward slash, it works, see following:
getDirectoryContents "C:/Users/User/Downloads/rwh-examples2/examples/ch09"

["Style.hs","SimpleFinder.hs","simplefinder.ghci","RecursiveContents.hs","recursivecontents.ghci","FoldDir.hs","flipMap.ghci","ControlledVisit.hs","BetterPredicate
.hs","betterpredicate.ghci","..","."]
*RecursiveContents>

actually, all Haskell commands fail with the backward slash...

patrick lynch  Jan 25, 2011 
Printed Page 214
2nd paragraph last sentence

it wraps a value with the monad's type constructor.

should be

it wraps a value into monad's type.

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
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  Apr 09, 2009 
Printed Page 224
last code block

? file: ch09/BetterPredicate.hs
constP :: a -> InfoP a
constP k _ _ _ _ = k

liftP' q f k w x y z = f w x y z `q` constP k w x y z

should be

? file: ch09/BetterPredicate.hs
constP :: a -> InfoP a
constP k _ _ _ _ = k

liftP' q f k = lift2 q f (constP k)

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
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  Oct 03, 2009 
Printed Page 238
8th line from bottom

There is an extra closed parenthesis.

... will be evaluated form left to right, as (a >>? b) >>? c).

should be
... will be evaluated form left to right, as (a >>? b) >>? c.

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
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  May 10, 2009 
Printed Page 246
11th line from bottom

This says that we can only put a type a into a Foo if a is a member of
the Eq typeclass.

should be

This says that we can only put a type a into a Bar if a is a member of
the Eq typeclass.

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
Printed Page 247
2nd paragraph in "Constraints on Type..."

(i.e., every element is bigger than the element below it),

should be

(i.e., every element is bigger than the element above it),

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
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  May 10, 2009 
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  Jan 04, 2009 
PDF, Other Digital Version Page 266
Figure 11-1

Legends of Figures 11-1 and 11-3 (p.268) have been interchanged:
"Figure 11-1. Revised coverage for module Prettify2: 52% [...]"
"Figure 11-3. Coverage for module Prettify2: 42% [...]"

BlaF  May 22, 2011 
PDF Page 270
1st code sample

checkDigit ds = 10 - (sum products `mod` 10)
should be
checkDigit ds = (10 - sum products `mod` 10) `mod` 10

Original checkDigit function cause Exception(Error in array index).

kariya_mitsuru  Feb 11, 2010 
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  May 10, 2009 
PDF Page 275
1st code sample

where (left, right) = splitAt 5 rest
should be
where (left, right) = splitAt 6 rest

kariya_mitsuru  Feb 11, 2010 
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  Apr 13, 2009 
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  May 10, 2009 
PDF Page 295
2nd code sample

buildMap = M.mapKeys (10 -)
should be
buildMap = M.mapKeys (\c -> (10 - c) `mod` 10)

Original buildMap function build map that has key 10, not key 0.

kariya_mitsuru  Feb 15, 2010 
Printed Page 328
9th line from bottom

... are its type constructor Maybe a, our ...

should be

... are its type constructor Maybe, our ...

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
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  Dec 16, 2008 
Printed Page 336
6th paragraph

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

Frans Slothouber  Feb 14, 2009 
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  Jan 20, 2009 
Printed Page 347
4th paragraph in "Almost a State..."

.. , and yet here we have a type with two parameters. The key is to
understand that we can partially apply a type just as ...

should be:

.. , and yet here we have a type constructor with two parameters. The
key is to understand that we can partially apply a type constructor just
as ...

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
PDF Page 348
3rd code sample

-> (s -> (b, s)) -- (makeStep result) newState
should be
-> (s -> (b, s)) -- makeStep result

kariya_mitsuru  Feb 17, 2010 
Printed Page 348
2nd paragraph

When we evaluate this, ... new function of type s -> (a, s)

should be

When we evaluate this, ... new function of type s -> (b, s)

Nellie McKesson
Nellie McKesson
 
May 24, 2011 
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  Jul 21, 2009 
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  Apr 06, 2009 
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  Mar 04, 2009 
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  Jan 07, 2009 
Printed Page 369
top

Code example doesn't run ... error output printed in book but text implies that there was no problem.

douglashendricks  Jan 28, 2012 
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  Feb 24, 2009 
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  May 10, 2009 
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  Mar 04, 2009 
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  Mar 04, 2009 
Printed Page 436
Top box

In the exercises at the top of page 436 it should be StateT instead of WriterT

Anonymous  Jun 09, 2014 
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  Feb 06, 2009 
Printed Page 495
2nd paragraph, ghci example

I had a great deal of trouble in loading Sqlite3 into my Windows Vista PC - I honestly don't know what version was finally loaded...
I couldn't get the following command to work - it complained that it couldn't find the database "test1.db":
conn <- connectSqlite3 "test1.db"
In desparation I finally created an empty file with this name and tried the command and it worked...

However, when I went on to page 496 in an attempt to create a table using the following command, it complained that the database could not be found:
run conn "CREATE TABLE test (id INTEGER NOT NULL, desc VARCHAR(80))" []


With this installation of Sqlite3, I cannot run it from the command line so, therefore, I'm unable to create a database from the command line, bummer...

I then went on to Chapter 22 and ran into a load problem ...

I'm so confused...I know this is 'open source' software, but should it be this difficult?

patrick lynch  Feb 02, 2011 
Printed Page 495
2nd paragraph, ghci example

I had a great deal of trouble in loading Sqlite3 into my Windows Vista PC - I honestly don't know what version was finally loaded...
I couldn't get the following command to work - it complained that it couldn't find the database "test1.db":
conn <- connectSqlite3 "test1.db"
In desparation I finally created an empty file with this name and tried the command and it worked...

However, when I went on to page 496 in an attempt to create a table using the following command, it complained that the database could not be found:
run conn "CREATE TABLE test (id INTEGER NOT NULL, desc VARCHAR(80))" []


With this installation of Sqlite3, I cannot run it from the command line so, therefore, I'm unable to create a database from the command line, bummer...

I then went on to Chapter 22 and ran into a load problem ...

I'm so confused...I know this is 'open source' software, but should it be this difficult?

patrick lynch  Feb 02, 2011 
Printed Page 497
...in the ghci example at the bottom of the page

first i had to change the first statement from:
ghci> conn <- connectSqlite3 "test1.db"
to [since I'm running a Windows Vista PC]:
ghci> conn <- connectSqlite3 "/users/user/test1.db"

then when i execute the following command:
run conn "INSERT INTO test VALUES (?, ?)" [toSql 0, toSql "zero"]
the following error message is returned:

<interactive>:1:43:
No instance for (Data.Convertible.Base.Convertible t SqlValue)
arising from a use of `toSql' at <interactive>:1:43-49
Possible fix:
add an instance declaration for
(Data.Convertible.Base.Convertible t SqlValue)
In the expression: toSql 0
In the third argument of `run', namely `[toSql 0, toSql "zero"]'
In the expression:
run conn "INSERT INTO test VALUES (?, ?)" [toSql 0, toSql "zero"]

patrick lynch  Feb 03, 2011 
Printed Page 517

I tried to download gtk2hs onto a Windows Vista PC using the link shown in the book, namely: http://www.haskell.org/gtk2hs/download/.
FYI: this link has been changed to: http://www.haskell.org/haskellwiki/Gtk2Hs.

Unfortunately, even with the assistance of the beginners@haskell.org I was unable to do so...If you know of another way of installing gtk2hs, please let me know.

Thank you

patrick lynch  Feb 06, 2011 
Printed Page 536
1st sentence of 1st paragraph of 'Safe Resource Management: A Good Idea, and Easy Besides'

"We can THE take the pattern ..." - should "THE" it be "then" of omitted entirely?

Pierre Caillaud  May 12, 2016 
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  Mar 30, 2009 
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  Mar 26, 2009 
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  Aug 03, 2009 
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  Jul 18, 2009 
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  Aug 05, 2009