Functional Programming using F#
Michael R. Hansen and Hans Rischel
Cambridge University Press 2013
ISBN 9781107019027
Corrections:
Page 20, line 18:
Give an evaluations
should be:
Give an evaluation
Page 24 line 3 from bottom:
the Unicode alphabet
should be replaced by:
UTF-16
Page 25, the first text line on the page should be extended as follows:
where the last one denotes the space character. A character is converted into its UTF-16
code by use of the function int, e.g. int 'a' = 97 and an UTF-16 code is converted to
a character by use of the function char, e.g. char 97 = 'a'.
Page 25, add following paragraph at the end of the page:
The character 'y' is sometimes a consonant (in 'yesterday', for example)
and sometimes a vowel (in 'city', for example). In Exercise 2.14 you are
asked to revise the above programs to accommodate this fact.
Page 26, line 9:
val it : string = "\"1234\""
should be:
val it : string = ""1234""
Page 31, the first paragraph on the page should be replaced by:
Overloading is extensively used in the .NET library (e.g. int: char -> int giving the
UTF-16 code, and int: string -> int converting a digit string to integer value). Typing
of arguments is frequently needed to resolve ambiguities. The user may declare overloaded
operators and functions inside a type declaration as explained in Section 7.3.
Page 38, Table 2.6, format of decimal constants should be:
{-}digitsM or
{-}digits.digitsM
Page 39, insert the following just above Summary:
Floating-point values should be used with care, because two expressions
with same value
may yield different results when evaluated using floating-point
arithmetic - try for instance
1.2=1.0+0.1+0.1. The reason is as follows:
A floating-point value (type float or float32) consists of binary numbers
mant and
exp called mantissa and exponent, each comprising a
fixed number of bits. The floating-point
value represents the number mant · 2exp. A number
like 1⁄10 can hence not be represented
by a floating-point value because it can't be written in the form
m · 2n with integers m
and n. The number may, however, be approximated by a floating-point
value representing a
number close to 1⁄10. The F# conversion of the string
"0.1" to a float value yields such
an approximation.
An arithmetic operation on floating-point values comprise a rounding
of the resulting
mantissa in order to fit the format, and the operation is therefore
only an approximation to
the corresponding (mathematical) operation on the represented numbers.
This book uses floating-point values only in a few examples (mainly of geometric nature)
and they are otherwise considered outside the scope of the book. You may consult books on
scientific computing for further information about how to use floating-point values.
Page 41, add the following exercise:
2.14 The character 'y' is sometimes a consonant (in 'yesterday', for example)
and sometimes a vowel (in 'city', for example). Revise the programs on Page 25
to accommodate this fact.
Page 48, line 20-22:
same function name or operator to arguments of different types, but an overloaded operator
... when applied to float's).
should be replaced by:
same function name or operator to arguments of different types, but the types of the arguments
has to be resolved during the compilation in case of overloading.
Polymorphism in F# can also be obtained using interface types (cf. Page 192).
Page 48, just above: 3.3 Example: ... add the following:
The string function (cf. Section 2.12) applies to values of any type, but it is not polymorphic.
The function toString declared by:
let toString x = string(box x)
is polymorphic and applies string to any value.
Page 55, line 17:
let b = ...
should be:
let d = ...
Page 61, line 15 from bottom:
Delete the word 'raise' from the program.
Page 63, line 3:
The following text and example should be added after line 3:
An exception declaration defines a constructor with corresponding
set of tagged values of type exn, for example:
exception Error of string;;
and another version of the area function from Page 61 could raise an Error exception:
let area x =
if not (isShape x)
then raise (Error "not a legal shape")
else ...
Page 81, line 7 to 6 from bottom:
expression (a closure) is considered a value expression because it is only evaluated further
when applied to an argument.
Should be:
declaration with argument pattern is always allowed at top level because a further evaluation
will only take place when the function is applied to an argument.
Page 82, line 18 to 19:
... does not contain type variables, ...
Should be:
... does not contain type variables or object interface types, ....
Page 84, line 8:
declare a auxiliary function
should be:
declare an auxiliary function
Page 90, last line:
p q [ x0; x1; x3; ... ; xn-1 ]
should be:
p q [ x0; x1; x2; ... ; xn-1 ]
Page 91, exercise 4.22, second line:
All commas in lists should be semicolons, i.e. the lists should be
[a0 ; a1 ; ...; an]
and [2; 0; 0; 1].
Page 94, Table 5.1:
The formulas for fold and foldBack should be:
fold f e
[x0 ; x1 ;
...; xn-2 ; xn-1] =
f (f ( ... (f (f e x0)
x1) ... ) xn-2) xn-1
and
foldBack g [x0 ; x1 ;
...; xn-2 ; xn-1] e =
g x0 (g x1
( ... (g xn-2 (g xn-1
e)) ··· ))
Page 103, line 15 from bottom:
g x0 (g x1 (foldBack g
[x1 ;x2 ; ...;xn-1] e))
should be:
g x0 (g x1 (foldBack g
[x2 ;x3 ; ...;xn-1] e))
Page 105, line 12 from bottom:
tation is based on a balanced binary tree representation ...
should be:
tation is based on a balanced binary tree representation (cf. Page 136) ...
Page 113, line 10 from bottom:
sets of entries
should be:
set of entries
Page 114, line 11 from bottom:
using balanced binary trees, ...
should be:
using balanced binary trees (cf. Page 136), ...
Page 147, Exercise 6.12, line 2 from bottom:
Declare the functions depthFirstFold and breadthFirstFoldBack on list trees, cf. Section 6.6.
should be:
Declare the functions depthFirstFoldBack and breadthFirstFold on list trees, cf. Section 6.6.
Page 155, add the following just above Table 7.3
Note that a terminating double semicolon (;;) may not occur anywhere
between the start of the type definition and the end of the type extension.
Page 162, Table 7.8:
Replace all occurences of
(x,y)
with
(x1,y1)
Page 166, Table 7.10, line 2 from bottom the table:
win.Show();;
should be:
win.Show();; // For Mono-platforms: replace 'win.Show()' with 'Application.Run(win)'
Page 166, line 1 from bottom:
5. The window is shown (win.Show()).
should be:
5. The window is shown using win.Show() on Windows and Application.Run(win) on Mono-platforms.
Page 168, Table 7.11:
Line 3 from top:
Replace
let map f ...
with:
let mapC f ...
Line 1 and 3 from bottom:
Replace
map
with:
mapC
Page 169, line 3 in Table 7.12 and line 2 below Table 7.12:
map
should be:
mapC
Page 172, line 8:
You should chose your own names ...
should be:
You should choose your own names ...
Page 183, line 13:
val it : int list = [1; 2]]
should be:
val it : int list = [1; 2]
Page 188, line 2:
reeds a text file
should be:
reads a text file
Page 188, line 12:
let file = ...
should be:
use file = ...
Page 189, line 17:
A selections of operations
should be:
A selection of operations
Page 189, Table 8.2, line 11:
Remove elements of other set
should be:
Remove elements outside other set
Page 191, line 18 from bottom:
set<'a>
should be:
Set<'a>
Page 191, line 15 from bottom:
map<'a,'b>
should be:
Map<'a,'b>
Page 194, line 13:
stores the enqueued value in the first free array location.
should be:
stores the enqueued value in the array location after the last value in the queue.
Page 208, line 8 from bottom:
gives a dramatically improvement
should be:
gives a dramatic improvement
Page 209, line 8 from bottom:
tail-recursive declarations of the above form in this subsection.
should be:
tail-recursive declarations of the above form in this section.
Tail calls are handled by F# in a special way: The stack frame of the preceding
function call is popped off the stack before the stack frame of the tail call is
pushed onto the stack. This is feasible because the tail call terminates any use
of bindings generated by the preceding function call.
Page 216, Exercise 9.7, Question 1:
A version fibA: int -> int -> int -> int ..... F-1 and F-2.
should be:
A version fibA: int -> int -> int -> int with two accumulating parameters a and b, where
fibA n a b = Fn when a = F0 and b = F1.
Page 217, a new exercise:
Exercise 9.15
Page 229. Replace the six lines just above Table 10.5 with:
The line-break string "\r\n" indicates
change of line in a text file handled by Text I/O.
The I/O functions insert and remove line-breaks in
a proper way: An input line obtained by
calling ReadLine contains no line-breaks
while each call of WriteLine adds a line-
break at the end of the line. The I/O functions
perform automatic conversion between the
UTF-16 character encoding used in the program and
the UTF-8 encoding used in the file.
Page 222, Table 10.2:
Add extra line in top section: . Matched by any character
Page 232, line 18:
system will in this case release the resources when the binding of the identifier reader
cannot be accessed any longer from the program. One usually ...
should be:
system will in this case release the resources when the program execution exits from the block
containing the use binding of the
identifier reader. One usually ...
Page 237, line 9:
can be found in
should be:
can be found in [9].
Page 243
The format of the MSDN web-pages has been changed after the chapter was written.
This gives corrections to Page 243:
Page 243, line 3-7 should be:
<a data-tochassubtree="true"
href="/en-us/library/ee353413.aspx" id="hh782276_VS.110_en-us"
title="Microsoft.FSharp.Collections Namespace">
Microsoft.FSharp.Collections Namespace</a>
Page 243, line 8:
System.Collections Namespace (F#)
should be:
Microsoft.FSharp.Collections Namespace
Page 243, line 9:
ee370255
should be:
ee353413
Page 244 and Table 10.16:
The format of the HTML sources of the MSDN web-pages
has been changed after the chapter was written.
nextInfo and getWebRefs functions have
been changed accordingly.
The corrected Page 244 and Table
10.16 are shown here
Page 253, line 5:
Extracting the third element
should be:
Extracting the fifth element
Page 254, Table 11.1, type for map:
map: ('a -> 'b) -> seq<'a> -> seq<'>
should be:
map: ('a -> 'b) -> seq<'a> -> seq<'b>
Page 255, Line 7 from below:
n ≥ i
should be:
i ≥ n
Page 268, Line 16 and Figure 11.2, Line 11:
SqlDataConnection<"Data Source=IMM-NBMRH\SQLEXPRESS;
should be:
SqlDataConnection<"Data Source=IMM-NBMRH\\SQLEXPRESS;
Page 280 line 9-10:
t.Bind ...
t.Return ...
should be:
member t.Bind ...
member t.Return ...
Page 297, first line:
let numReg = Regex @"\G\s*((?:\053|-|)\s*[0-9]+)";;
should be:
let numReg = Regex @"\G\s*((?:\053|-|)[0-9]+)";;
Page 297, line 9 from bottom:
The associations of the operators are capture in
should be:
The associations of the operators are captured in
Page 307, line 9:
been introduced above, so the grammar can ...
should be:
been introduced above, so the grammar on Page 297 can ...
Page 317, last 3 lines in Table 13.3 should be:
Makes current task a wait item. The argument is a function that is called with the
triple of continuations as the argument. This function should save one or more of
the continuations in variables. The task continues when a saved continuation is called.
Page 320, line 2:
continuation.
should be:
continuation (determined e.g. by a try...with...
construct, cf. Section 3.10).
Page 320, from line 13 to bottom:
The examples are not correct.
The corrected Page 320 is found here.
Page 321, line 6 to 8:
Each execution ... in the function declaration.
should be
Each execution of an asynchronous computation with
possible cancellation should have a
fresh cancellation token and this object should
be disposed afterwards. The below
dialogue program ensures this by means of a local use-binding (cf. Page 327).
Page 322. Add this comment as line 2 in Table 13.4:
// To be used only in single-thread operation
Page 323, Table 13.5, line 1 from bottom the table:
window.Show();;
should be:
window.Show();; // For Mono-platforms: replace 'window.Show()' with 'Application.Run(window)'
Page 324, line 5 to 6:
Note that the program ... for the book.
should be
The start-up using Async.StartImmediate implies that the event-driven dialogue
program is executed by a single thread. This ensures the integrity of mutable data,
including the event queue. The complete program is found at the homepage of the book.
Page 340 lines 1 to 3:
Elements in HTML appear in pairs of start and end
elements, and some elements may
contain attributes. The line break element <br />
is considered a (degenerated) pair of
start and end element <br></br>.
should be
Elements in HTML appear in pairs
<name ... > ... </name ... >
of start and end element,
and some elements may contain attributes. An element of form
<... /> (like the line break
element <br />) is considered a (degenerated) pair of start and end element.
Pages 344 and 345:
The format of the HTML sources of the MSDN web-pages
has been changed after the chapter was written.
The nextLevelRefs program has been changed accordingly.
The corrected pages 344 and 345
are shown here
Comments to:
Michael R. Hansen
Last update: August 20, 2020