+ plus x y z = x+y+z + x `plus` y = \ z > x+y+z + (x `plus` y) z = x+y+z +" +(This change makes explicit that an infix operator with more than two arguments +can have all of them on the LHS.) + +
+"module A( null, nonNull ) where import Prelude hiding( null ) null, nonNull :: Int > Bool @@ 160,20 +196,29 @@ The latter would be ambiguous without the "hiding(null)" on the Every module that imports A unqualified, and then makes an unqualified reference to null must also resolve the ambiguous use of null just as A does. Thus there is little danger of accidentally shadowing Prelude names. +Prelude names." + +
fromRealFrac :: (RealFrac a, Fractional b) => a > b@@ 190,19 +235,42 @@ After the first paragraph give the following type signature: Also add an index entry for userError on this page. (These changes are purely presentational.) +
+ instance Monad IO where + ...bindings for return, (>>=), (>>) + + fail s = ioError (userError s) +" +
enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]+
+ fail s = ioError (userError s) ++
+ map :: (a > b) > [a] > [b] ++
@@ 216,17 +284,66 @@ Replace the definition of (!!) with the following: (The original version had the property that ([] !! 100) reported "index too large".) +
+scanl :: (a > b > a) > a > [b] > [a] +scanl f q xs = q : (case xs of + [] > [] + x:xs > scanl f (f q x) xs) + +scanl1 :: (a > a > a) > [a] > [a] +scanl1 f (x:xs) = scanl f x xs +scanl1 _ [] = [] + +scanr1 :: (a > a > a) > [a] > [a] +scanr1 f [] = [] +scanr1 f [x] = [x] +scanr1 f (x:xs) = f x q : qs + where qs@(q:_) = scanr1 f xs ++The effect is to make both functions defined on the empty list. + + +
+ take :: Int > [a] > [a] + take n _  n <= 0 = [] + take _ [] = [] + take n (x:xs) = x : take (n1) xs + + drop :: Int > [a] > [a] + drop n xs  n <= 0 = xs + drop _ [] = [] + drop n (_:xs) = drop (n1) xs + + splitAt :: Int > [a] > ([a],[a]) + splitAt n xs = (take n xs, drop n xs) ++The effect is that all three functions are defined on negative arguments. This +is a semantic change. +
+ recip (x:%y) = y % x ++The effect of this change is to use the "smart constructor", %, instead +doing it by hand. In particular, an error will be raised if y is zero. +
+  NB: replacing "null (range b)" by "not (l <= h)" +  fails if the bounds are tuples. For example, +  (1,2) <= (2,1) +  but the range is nevertheless empty +  range ((1,2),(2,1)) = [] ++(This simply fixes a misleading comment.) +
@@ 302,18 +437,69 @@ Add an index entry for nub.
+ partition :: (a > Bool) > [a] > ([a],[a]) + partition p xs = (filter p xs, filter (not . p) xs) ++This simply makes it agree with the definition on page 30 (Section 7.3). + +
+ maximumBy :: (a > a > Ordering) > [a] > a + maximumBy cmp [] = error "List.maximumBy: empty list" + maximumBy cmp xs = foldl1 max xs + where + max x y = case cmp x y of + GT > x + _ > y + + minimumBy :: (a > a > Ordering) > [a] > a + minimumBy cmp [] = error "List.minimumBy: empty list" + minimumBy cmp xs = foldl1 min xs + where + min x y = case cmp x y of + GT > y + _ > x ++NOTE: this is a semantic change, but it makes the definitions +consistent with the other "By" functions, and with the signatures given on page 28. +
try :: IO a > IO (Either IOError a)+
+"Implementations should enforce as far as possible, locally to the +Haskell process, multiplereader singlewriter locking on files. +That is, there may either be many handles on the same file which manage +input, or just one handle on the file which manages output. If any +open or semiclosed handle is managing a file for output, no new +handle can be allocated for that file. If any open or semiclosed +handle is managing a file for input, new handles can only be allocated +if they do not manage output. Whether two files are the same is +implementationdependent, but they should normally be the same if they +have the same absolute path name and neither has been renamed, for +example. + +Warning: the readFile operation (Section 7.1 of the Haskell Language Report) +holds a semiclosed handle on the file until the entire contents of the file have been +consumed. It follows that an attempt to write to a file (using writeFile, for example) +that was earlier opened by readFile will usually result in +failure with isAlreadyInUseError." +
There is also a complete index.

+Copyright (c) Simon Peyton Jones and John Hughes.
+
+ The authors intend this Report to belong to the entire Haskell
+community, and so we grant permission to copy and distribute it for
+any purpose, provided that it is reproduced in its entirity,
+including this Notice. Modified versions of this Report may also be
+copied and distributed for any purpose, provided that the modified
+version is clearly presented as such, and that it does not claim to be
+a definition of the language Haskell 98.
The master version of the Haskell Library Report is at haskell.org. Any corrections or diff git a/libraries/introduction.verb b/libraries/introduction.verb index 29db1f1..68f8635 100644  a/libraries/introduction.verb +++ b/libraries/introduction.verb @@ 18,6 +18,15 @@ which are not a recognized part of the \Haskell{} standard. The latest version of this report, as well many other available libraries, can be found on the web at @http://haskell.org@. +\subsection*{The April 2001 Revision} + +Both Haskell 98 Reports were revised in April 2001, to incorporate +dozens of typographical errors and presentational improvements. A +complete list of all changes can be found at @http:://haskell.org@. + + +\subsection*{Acknowledgements} + We would like to express our thanks to those who have contributed directly or indirectly to this report without being named as authors, including @@ 33,6 +42,9 @@ Graeme Moss, Sven Panne, Keith Wansbrough. +In addition, many people named in the Acknowledgements to the Haskell 98 Language +Report also contributed to the Library Report. + \clearpage \section{Introduction} \label{introduction} diff git a/libraries/io.verb b/libraries/io.verb index 7e02d42..763df5f 100644  a/libraries/io.verb +++ b/libraries/io.verb @@ 146,17 +146,29 @@ enough information to identify the handle for debugging. A handle is equal according to @==@ only to itself; no attempt is made to compare the internal state of different handles for equality. +\subsubsection{Standard Handles} +\label{StandardHandles} +\index{standard handles} + +Three handles are allocated during program initialisation. The first +two (@stdin@\indextt{stdin} and @stdout@\indextt{stdout}) manage input or output from the \Haskell{} +program's standard input or output channel respectively. The third +(@stderr@\indextt{stderr}) manages output to the standard error channel. These +handles are initially open. + \subsubsection{SemiClosed Handles} \label{SemiClosed} \index{semiclosed handles} The operation @hGetContents@\indextt{hGetContents} puts a handle "hdl" into an intermediate +The operation "@hGetContents@ hdl"\indextt{hGetContents} +puts a handle "hdl" into an intermediate state, {\em semiclosed}. In this state, "hdl" is effectively closed, but items are read from "hdl" on demand and accumulated in a special stream returned by @hGetContents@~"hdl". Any operation except for @hClose@ that fails because a handle is closed, also fails if a handle is semiclosed. A semiclosed handle +Any operation that fails because a handle is +closed, also fails if a handle is semiclosed. The only exception is @hClose@. +A semiclosed handle becomes closed: \begin{itemize} \item @@ 173,16 +185,28 @@ associated stream becomes fixed, and is the list of those items which were successfully read from that handle. Any I/O errors encountered while a handle is semiclosed are simply discarded. +\subsubsection{File locking} \subsubsection{Standard Handles} \label{StandardHandles} \index{standard handles} +Implementations should enforce as far as possible, locally to the +\Haskell{} process, multiplereader singlewriter locking on files. +That is, \emph{there may either be many handles on the same file which manage +input, or just one handle on the file which manages output}. If any +open or semiclosed handle is managing a file for output, no new +handle can be allocated for that file. If any open or semiclosed +handle is managing a file for input, new handles can only be allocated +if they do not manage output. Whether two files are the same is +implementationdependent, but they should normally be the same if they +have the same absolute path name and neither has been renamed, for +example. + +{\em Warning}: the @readFile@ operation (Section 7.1 of the Haskell Language Report) +holds a semiclosed handle on the file until the entire contents of the file have been +consumed. It follows that an attempt to write to a file (using @writeFile@, for example) +that was earlier opened by @readFile@ will usually result in +failure with @isAlreadyInUseError@. +\indextt{readFile} +\indextt{writeFile} Three handles are allocated during program initialisation. The first two (@stdin@\indextt{stdin} and @stdout@\indextt{stdout}) manage input or output from the \Haskell{} program's standard input or output channel respectively. The third (@stderr@\indextt{stderr}) manages output to the standard error channel. These handles are initially open. \subsection{Opening and Closing Files} \label{OpeningClosing} @@ 218,27 +242,15 @@ position is 0). The initial buffer mode is implementationdependent. If @openFile@ fails on a file opened for output, the file may still have been created if it did not already exist. Implementations should enforce as far as possible, locally to the \Haskell{} process, multiplereader singlewriter locking on files. Thus there may either be many handles on the same file which manage input, or just one handle on the file which manages output. If any open or semiclosed handle is managing a file for output, no new handle can be allocated for that file. If any open or semiclosed handle is managing a file for input, new handles can only be allocated if they do not manage output. Whether two files are the same is implementationdependent, but they should normally be the same if they have the same absolute path name and neither has been renamed, for example.  {\em Error reporting}: the @openFile@ computation may fail with @isAlreadyInUseError@ if the file is already open and cannot be reopened; @isDoesNotExistError@ if the file does not exist; or @isPermissionError@ if the user does not have permission to open the file.  %ADG: this is obvious! %KH: Not really. It's actually quite subtle! +\indextt{isAlreadyInUseError} +\indextt{isDoesNotExistError} +\indextt{isPermissionError} \subsubsection{Closing Files} \label{Closing} @@ 485,6 +497,7 @@ character is available. the @hLookahead@ computation may fail with: @isEOFError@ if the end of file has been reached. +\subsubsection{Reading The Entire Input} \label{hGetContents} \index{get the contents of a file} @@ 496,6 +509,8 @@ by "hdl", which is made semiclosed. the @hGetContents@ computation may fail with: @isEOFError@ if the end of file has been reached. +\subsubsection{Text Output} + Computation @hPutChar@~"hdl"~"c"\indextt{hPutChar} writes the character "c" to the file or channel managed by "hdl". Characters may be buffered if buffering is enabled for "hdl". @@ 539,7 +554,9 @@ main = do x2 < readNum putStr ("Their sum is " ++ show (x1+x2) ++ "\n") where readNum :: IO Integer  readNum = do { line < getLine; readIO line } +  Need a type signature for +  readLn to avoid ambiguity + readNum = readLn @ \eprog diff git a/libraries/ix.verb b/libraries/ix.verb index cb42d85..b5cc84f 100644  a/libraries/ix.verb +++ b/libraries/ix.verb @@ 5,7 +5,7 @@ \outline{ \inputHS{headers/Ix} } The @Ix@ class is used to map a continuous subrange of values in a +The @Ix@ class is used to map a contiguous subrange of values in a type onto integers. It is used primarily for array indexing (see Section~\ref{arrays}). The @Ix@ class contains the methods @range@\indextt{range}, diff git a/libraries/library.verb b/libraries/library.verb index b1c2e54..7b5e311 100644  a/libraries/library.verb +++ b/libraries/library.verb @@ 1,5 +1,5 @@ % % $Header: /home/cvs/root/haskellreport/libraries/library.verb,v 1.1 2001/03/28 14:16:23 simonpj Exp $ +% $Header: /home/cvs/root/haskellreport/libraries/library.verb,v 1.2 2001/05/29 15:39:59 simonpj Exp $ % % NOTE: % The formatting of this report and the ``new font selection scheme'' @@ 412,29 +412,22 @@ {\Large\bf for the} \\[.1in] {\huge\bf Haskell 98} \\[.3in] {\LARGE\bf Programming Language} \\[.3in] {\large\bf 1 February 1999} +{\large\bf FILL IN DATE!} \end{center} \vspace{.15in} \begin{center} \large Simon Peyton Jones$^8$ [editor] \\ John Hughes$^3$ [editor] \\ Lennart Augustsson$^3$ \\ Dave Barton$^7$ \\ Brian Boutel$^4$ \\ Warren Burton$^5$ \\ Joseph Fasel$^6$ \\ Kevin Hammond$^2$ \\ Ralf Hinze$^{12}$ \\ Paul Hudak$^1$ \\ Thomas Johnsson$^3$ \\ Mark Jones$^9$ \\ John Launchbury$^{14}$ \\ Erik Meijer$^{10}$\\ John Peterson$^1$ \\ Alastair Reid$^1$ \\ Colin Runciman$^{13}$ \\ Philip Wadler$^{11}$ \\ +\begin{tabular}{l@@{\hspace{5mm}}l} +Simon Peyton Jones$^8$ [editor] & John Hughes$^3$ [editor] \\ +Lennart Augustsson$^3$ & Dave Barton$^7$ \\ +Brian Boutel$^4$ & Warren Burton$^5$ \\ +Joseph Fasel$^6$ & Kevin Hammond$^2$ \\ +Ralf Hinze$^{12}$ & Paul Hudak$^1$ \\ +Thomas Johnsson$^3$ & Mark Jones$^9$ \\ +John Launchbury$^{14}$ & Erik Meijer$^{10}$ \\ +John Peterson$^1$ & Alastair Reid$^1$ \\ +Colin Runciman$^{13}$ & Philip Wadler$^{11}$ +\end{tabular} \end{center} \vspace{.15in} @@ 456,6 +449,17 @@ Authors' affiliations: (14)~Oregon Graduate Institute \end{quotation} \vspace{.2in} +\begin{center} +Copyright (c) Simon Peyton Jones and John Hughes. +\end{center} + +{\em The authors intend this Report to belong to the entire Haskell +community, and so we grant permission to copy and distribute it for +any purpose, provided that it is reproduced in its entireity, +including this Notice. Modified versions of this Report may also be +copied and distributed for any purpose, provided that the modified +version is clearly presented as such, and that it does not claim to be +a definition of the language Haskell 98.} } \end{titlepage} diff git a/libraries/list.verb b/libraries/list.verb index 34e1eae..0f38bb6 100644  a/libraries/list.verb +++ b/libraries/list.verb @@ 20,7 +20,8 @@ in @list@ as @Just index@. @Nothing@ is returned if @not (val `elem` list)@. Function @elemIndices val list@\indextt{elemIndices} returns an inorder list of indices, giving the occurrences of @val@ in @list@. Function @find@ returns the first element of a list that satisfies a predicate, +Function @find@\indextt{find} +returns the first element of a list that satisfies a predicate, or Nothing, if there is no such element. @findIndex@ returns the corresponding index. @findIndices@ returns a list of all such indices. @@ 34,8 +35,16 @@ lists don't contain duplicates, provided that their first argument contains no duplicates. \begin{itemize} +\item +@nub@\indextt{nub} removes duplicate elements from a list. For example: +\bprog +@ + nub [1,3,1,4,3,3] = [1,3,4] +@ +\eprog \item @delete x@ removes the first occurrence of @x@ from its list argument, +@delete x@\indextt{delete} +removes the first occurrence of @x@ from its list argument, e.g., \bprog @ @@ 44,10 +53,13 @@ e.g., \eprog \item @(\\)@ is list difference (nonassociative). In the result of @xs \\ ys@, +@(\\)@\indextt{(\\)} is list +difference (nonassociative). In the result of @xs \\ ys@, the first occurrence of each element of @ys@ in turn (if any) has been removed from @xs@. Thus, @(xs ++ ys) \\ xs == ys@. @union@ is list union, e.g., + +\item +@union@\indextt{union} is list union, e.g., \bprog @ "dog" `union` "cow" == "dogcw" @@ 55,7 +67,7 @@ has been removed from @xs@. Thus, @(xs ++ ys) \\ xs == ys@. \eprog \item @intersect@ is list intersection, e.g., +@intersect@\indextt{intersect} is list intersection, e.g., \bprog @ intersect [1,2,3,4] `intersect` [2,4,6,8] == [2,4] @@ 67,7 +79,8 @@ has been removed from @xs@. Thus, @(xs ++ ys) \\ xs == ys@. \begin{itemize} \item @intersperse sep@ inserts @sep@ between the elements of its list argument, +@intersperse sep@\indextt{intersperse} +inserts @sep@ between the elements of its list argument, e.g., \bprog @ @@ 76,7 +89,7 @@ e.g., \eprog \item @transpose@ transposes the rows and columns of its argument, +@transpose@\indextt{transpose} transposes the rows and columns of its argument, e.g., \bprog @ @@ 85,7 +98,8 @@ e.g., \eprog \item @partition@ takes a predicate and a list and returns a pair of lists: +@partition@\indextt{partition} +takes a predicate and a list and returns a pair of lists: those elements of the argument list that do and do not satisfy the predicate, respectively; i.e., \bprog @@ 95,12 +109,13 @@ predicate, respectively; i.e., \eprog \item @sort@/@sortBy@ implement a stable sorting algorithm, here specified +@sort@/@sortBy@\indextt{sort}\indextt{sortBy} +implement a stable sorting algorithm, here specified in terms of the @insertBy@ function, which inserts objects into a list according to the specified ordering relation. \item @group@ splits its list argument into a list of lists of equal, adjacent +@group@\indextt{group} splits its list argument into a list of lists of equal, adjacent elements. For exmaple \bprog @ @@ 109,7 +124,7 @@ elements. For exmaple \eprog \item @inits@ returns the list of initial segments of its argument list, shortest first. +@inits@\indextt{inits} returns the list of initial segments of its argument list, shortest first. \bprog @ inits "abc" == ["","a","ab","abc"] @@ 117,7 +132,8 @@ elements. For exmaple \eprog \item @tails@ returns the list of all final segments of its argument list, longest first. +@tails@\indextt{tails} +returns the list of all final segments of its argument list, longest first. \bprog @ tails "abc" == ["abc", "bc", "c",""] @@ 125,17 +141,19 @@ elements. For exmaple \eprog \item @mapAccumL f s l@ applies @f@ to an accumulating ``state'' parameter @s@ +@mapAccumL f s l@\indextt{mapAccumL} +applies @f@ to an accumulating ``state'' parameter @s@ and to each element of @l@ in turn. \item @mapAccumR@ is similar to @mapAccumL@ except that the list +@mapAccumR@\indextt{mapAccumR} +is similar to @mapAccumL@ except that the list is processed from righttoleft rather than lefttoright. \end{itemize} \subsection{@unfoldr@} The @unfoldr@ function undoes a @foldr@ operation. Note that, +The @unfoldr@\indextt{unfoldr} function undoes a @foldr@ operation. Note that, in general, only invertible functions can be unfolded. \bprog @ diff git a/libraries/random.verb b/libraries/random.verb index ca3fd4d..a19cf3d 100644  a/libraries/random.verb +++ b/libraries/random.verb @@ 30,19 +30,38 @@ The class @RandomGen@ provides a common interface to random number generators. \bprog @ class RandomGen g where  next :: g > (Int, g)  split :: g > (g, g) + genRange :: g > (Int,Int) + next :: g > (Int, g) + split :: g > (g, g) + +  Default method + genRange g = (minBound,maxBound) @ \eprog \indextt{next} \indextt{split} +\indextt{genRange} \indextt{RandomGen} \begin{itemize} \item The @next@ operation allows one to extract at least 30 bits (one @Int@'s worth) from the generator, returning a new generator as well. The integer returned may be positive or negative. +\item The @genRange@ operation yields the range of values returned by +the generator. \item The @split@ operation allows one to obtain two distinct random number +\item The @next@ operation returns an @Int@ that is uniformly distributed +in the range returned by @genRange@ (including both end points), and a new +generator. +It is required that: +\begin{itemize} +\item If $(a,b) ~=~ @genRange@~ g$, then $a \leq b$. +\item $@genRange@~\bot ~\neq~ \bot$. +\end{itemize} +The second condition ensures that @genRange@ cannot examine its +argument, and hence the value it returns can be determined only by the +instance of @RandomGen@. That in turn allows an implementation to make +a single call to @genRange@ to establish a generator's range, without +being concerned that the generator returned by (say) @next@ might have a different +range to the generator passed to @next@. + +\item The @split@ operation allows one to obtain two independent random number generators. This is very useful in functional programs (for example, when passing a random number generator down to recursive calls), but very little work has been done on statistically robust implementations of @split@ @@ 64,13 +83,15 @@ type @StdGen@: \eprog \indextt{StdGen} \indextt{mkStdGen} +The @StgGen@ instance of @RandomGen@ has a @genRange@ of at least 30 bits. + The result of repeatedly using @next@ should be at least as statistically robust as the ``Minimal Standard Random Number Generator'' described by [2,3]. Until more is known about implementations of @split@, all we require is that @split@ deliver generators that are (a) not identical and (b) independently robust in the sense just given. The @show@/@Read@ instances of @StdGen@ provide a primitive way to save +The @Show@/@Read@ instances of @StdGen@ provide a primitive way to save the state of a random number generator. It is required that @read (show g) == g@. @@ 89,6 +110,26 @@ to produce distinct generators. Programmers may, of course, supply their own instances of @RandomGen@. +{\em Implementation warning.} A superficially attractive implementation of @split@ is +\bprog +@ + instance RandomGen MyGen where + ... + split g = (g, variantOf g) +@ +\eprog +Here, @split@ returns @g@ itself and a new generator derived from @g@. +But now consider these two apparentlyindependent generators: +\bprog +@ + g1 = snd (split g) + g2 = snd (split (fst (split g))) +@ +\eprog +If @split@ genuinely delivers independent generators (as specified), then @g1@ and +@g2@ should be independent, but in fact they are both equal to @variantOf g@. +Implementations of the above form do not meet the specification. + \subsection{The @Random@ class} With a source of random number supply in hand, the @Random@ class allows @@ 176,7 +217,7 @@ generator (see Section~\ref{globalrng}). There is a single, implicit, global random number generator of type @StdGen@, held in some global variable maintained by the @IO@ monad. It is initialised automatically in some systemdependent fashion, for example, by using the time of day, or Linux's kernal random number generator. +for example, by using the time of day, or Linux's kernel random number generator. To get deterministic behaviour, use @setStdGen@. \bprog @ diff git a/report/Makefile b/report/Makefile index a4ee518..897f88e 100644  a/report/Makefile +++ b/report/Makefile @@ 4,7 +4,7 @@ ########################################## # What to make if you type 'make' default: haskell.ps html +default: haskell.ps.gz html # Begin by saying # touch haskell.idx @@ 36,6 +36,8 @@ EXPAND = expand # Files ######################################### +RELEASE_DIR = ../haskell98revised + PARTS = preface13.tex isochars.tex \ intro.tex lexemes.tex exps.tex \ decls.tex modules.tex basic.tex io13.tex \ @@ 151,12 +153,10 @@ haskelllibrariesx.dvi : sigplan_haskelllibraries.dvi haskell.ps : haskell.dvi dvips haskell.dvi o haskell.ps   publish: haskell.ps html  gzip < haskell.ps > y:Haskell/haskell98report/haskell.ps.gz  cp haskell98reporthtml/* y:Haskell/haskell98report  tar cvf  haskell98reporthtml  gzip > y:Haskell/haskell98report/haskell98reporthtml.tar.gz +release: haskell.ps html + gzip < haskell.ps > $(RELEASE_DIR)/haskell.ps.gz + cp r haskell98reporthtml $(RELEASE_DIR) + tar cvf  haskell98reporthtml  gzip > $(RELEASE_DIR)/haskell98reporthtml.tar.gz publishpdf: report.pdf gzip < report.pdf > y:Haskell/haskell98report/report.pdf.gz diff git a/report/Prelude.hs b/report/Prelude.hs index 259abaa..08ad7c0 100644  a/report/Prelude.hs +++ b/report/Prelude.hs @@ 61,7 +61,7 @@ infixr 0 $, $!, `seq` class Eq a where (==), (/=) :: a > a > Bool   Minimal complete defintion: +  Minimal complete definition:  (==) or (/=) x /= y = not (x == y) x == y = not (x /= y) @@ 109,6 +109,7 @@ class Enum a where pred = toEnum . (subtract 1) . fromEnum enumFrom x = map toEnum [fromEnum x ..] enumFromTo x y = map toEnum [fromEnum x .. fromEnum y] + enumFromThen x y = map toEnum [fromEnum x, fromEnum y, ..] enumFromThenTo x y z = map toEnum [fromEnum x, fromEnum y .. fromEnum z] @@ 427,7 +428,7 @@ instance Monad IO where return = ... m >> k = m >>= \_ > k  fail s = error s + fail s = ioError (userError s)  Ordering type @@ 479,7 +480,7 @@ instance RealFloat Double where ...  The Enum instances for Floats and Doubles are slightly unusual.  The `toEnum' function truncates numbers to Int. The definitions  of enumFrom and enumFromThen allow floats to be used in arithmetic  series: [0,0.1 .. 1.0]. However, roundoff errors make these somewhat + series: [0,0.1 .. 0.95]. However, roundoff errors make these somewhat  dubious. This example may have either 10 or 11 elements, depending on  how 0.1 is represented. diff git a/report/PreludeList.hs b/report/PreludeList.hs index 67ad5fa..fb3d91c 100644  a/report/PreludeList.hs +++ b/report/PreludeList.hs @@ 8,7 +8,7 @@ module PreludeList ( take, drop, splitAt, takeWhile, dropWhile, span, break, lines, words, unlines, unwords, reverse, and, or, any, all, elem, notElem, lookup,  Sum, product, maximum, minimum, concatMap, + sum, product, maximum, minimum, concatMap, zip, zip3, zipWith, zipWith3, unzip, unzip3) where @@ 19,7 +19,7 @@ infixr 5 ++ infix 4 `elem`, `notElem`  Map and append map :: (a > b) > [a] > [a] +map :: (a > b) > [a] > [b] map f [] = [] map f (x:xs) = f x : map f xs @@ 70,10 +70,10 @@ length (_:l) = 1 + length l  List index (subscript) operator, 0origin (!!) :: [a] > Int > a (x:_) !! 0 = x (_:xs) !! n  n > 0 = xs !! (n1) (_:_) !! _ = error "Prelude.!!: negative index" +xs !! n  n < 0 = error "Prelude.!!: negative index" [] !! _ = error "Prelude.!!: index too large" +(x:_) !! 0 = x +(_:xs) !! n = xs !! (n1)  foldl, applied to a binary operator, a starting value (typically the  leftidentity of the operator), and a list, reduces the list using @@ 102,7 +102,7 @@ scanl f q xs = q : (case xs of scanl1 :: (a > a > a) > [a] > [a] scanl1 f (x:xs) = scanl f x xs scanl1 _ [] = error "Prelude.scanl1: empty list" +scanl1 _ [] = []  foldr, foldr1, scanr, and scanr1 are the righttoleft duals of the  above functions. @@ 121,11 +121,11 @@ scanr f q0 [] = [q0] scanr f q0 (x:xs) = f x q : qs where qs@(q:_) = scanr f q0 xs scanr1 :: (a > a > a) > [a] > [a] scanr1 f [x] = [x] scanr1 f (x:xs) = f x q : qs  where qs@(q:_) = scanr1 f xs scanr1 _ [] = error "Prelude.scanr1: empty list" +scanr1 :: (a > a > a) > [a] > [a] +scanr1 f [] = [] +scanr1 f [x] = [x] +scanr1 f (x:xs) = f x q : qs + where qs@(q:_) = scanr1 f xs  iterate f x returns an infinite list of repeated applications of f to x:  iterate f x == [x, f x, f (f x), ...] @@ 154,22 +154,17 @@ cycle xs = xs' where xs' = xs ++ xs'  is equivalent to (take n xs, drop n xs). take :: Int > [a] > [a] take 0 _ = [] +take n _  n <= 0 = [] take _ [] = [] take n (x:xs)  n > 0 = x : take (n1) xs take _ _ = error "Prelude.take: negative argument" +take n (x:xs) = x : take (n1) xs drop :: Int > [a] > [a] drop 0 xs = xs +drop n xs  n <= 0 = xs drop _ [] = [] drop n (_:xs)  n > 0 = drop (n1) xs drop _ _ = error "Prelude.drop: negative argument" +drop n (_:xs) = drop (n1) xs splitAt :: Int > [a] > ([a],[a]) splitAt 0 xs = ([],xs) splitAt _ [] = ([],[]) splitAt n (x:xs)  n > 0 = (x:xs',xs'') where (xs',xs'') = splitAt (n1) xs splitAt _ _ = error "Prelude.splitAt: negative argument" +splitAt n xs = (take n xs, drop n xs)  takeWhile, applied to a predicate p and a list xs, returns the longest  prefix (possibly empty) of xs of elements that satisfy p. dropWhile p xs diff git a/report/basic.verb b/report/basic.verb index c1a7eaf..a75166b 100644  a/report/basic.verb +++ b/report/basic.verb @@ 1,5 +1,5 @@ % % $Header: /home/cvs/root/haskellreport/report/basic.verb,v 1.1 2001/03/28 14:13:42 simonpj Exp $ +% $Header: /home/cvs/root/haskellreport/report/basic.verb,v 1.2 2001/05/29 15:40:00 simonpj Exp $ % %**
+Copyright (c) Simon Peyton Jones and John Hughes.
+
+ The authors intend this Report to belong to the entire Haskell
+community, and so we grant permission to copy and distribute it for
+any purpose, provided that it is reproduced in its entirity,
+including this Notice. Modified versions of this Report may also be
+copied and distributed for any purpose, provided that the modified
+version is clearly presented as such, and that it does not claim to be
+a definition of the language Haskell 98.