Future changes are in The Revised Report bug list.
"Copyright (c) Simon Peyton Jones.
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."
"Haskell has adopted many of the convenient syntactic structures that have become popular in functional programming. In this Report, the meaning of such syntactic sugar is given by translation into simpler constructs. If these translations are applied exhaustively, the result is a program written in a small subset of Haskell that we call the Haskell kernel."
"Although the kernel is not formally specified, it is essentially a slightly sugared variant of the lambda calculus with a straightforward denotational semantics. The translation of each syntactic structure into the kernel is given as the syntax is introduced. This modular design facilitates reasoning about Haskell programs and provides useful guidelines for implementors of the language."
(The intent here is to avoid the common misconception that the kernel is a formally specified thing.)
comment -> dashes [ any_<symbol> { any } \] newline
(This ensures that "--+", for example, does not start a comment.)
lexeme -> qvarid | qconid | qvarsym | qconsym | literal | special | reservedop | reservedid
whitechar -> newline | vertab | space | tab | uniWhite newline -> return linefeed | return | linefeed | formfeed(This means that CR, LF, or CRLF (remember maximal munch), are all valid 'newline' separators, and the same sequence of characters should therefore work on any Haskell implementation.)
ANY -> graphic | whitechar(This is nicely similar to the production for "any".)
uniDigit -> any Unicode decimal digit
symbol -> ascSymbol | uniSymbol< special | _ | : | " | ' >
(The maximal munch rule is correct, but it's not true that it only takes one character of lookahead. Consider "F. 9. 0o 0x 9.0e+f", which should lex as "F . 9 . 0 o 0 x 9.0 e + f" but that needs up to two additional characters of lookahead.)
float -> decimal . decimal [exponent]
| decimal exponent
exponent -> (e | E) [+ | -] decimal
(This change means that 20e3 is a floating-point literal. There is a corresponding change
to the lexer on p114.)
"The character type Char is an enumeration whose values represent Unicode characters [10]." Similarly, remove the final clause "...in the range [0..2^16 - 1]".
(This change removes the commitment to 16-bit Unicode. The result is that the Report is even vaguer than before about the range of Unicode that a compiler is obliged to accept, but this confusion is in large part Unicode's fault, and is not readily fixed in a revision of this nature.)
"If the indentation of the non-brace lexeme immediately following a where, let, do or of is less than or equal to the current indentation level, then instead of starting a layout, an empty list "{}" is inserted, and layout processing occurs for the current level (i.e. insert a semicolon or close brace)."
size :: Stack a -> Int
"Free variables and constructors used in these translations always refer to entities defined by the Prelude. For example, ``concatMap'' used in the translation of list comprehensions (Section 3.11) means the concatMap defined by the Prelude, regardless of what is in scope where the list comprehension is used."
(Clarification only.)
| '(' lexp(i) qop(l,i) ')' left section
| '(' qop(r,i)<-> rexp(i) ')' right section
and change the othe right-section production to:
| '(' qop(a,i)<-> exp(i+1) ')' right section
(This brings the formal syntax into line with the
words in Section 3.5. The grammar now follows the way that qfunlhs is defined.
There is no ambiguity, because an exp(i+1) is not an lexp(i).)
The exclusion of "-" from right sections is also new [May 2002]; it is necessary to prevent overlap with the unary-minus syntax.
A note about parsing. Expressions that involve the interaction of fixities with the let/lambda meta-rule may be hard to parse. For example, the expression
let x = True in x == x == Truecannot possibly mean
let x = True in (x == x == True)because (==) is a non-associative operator; so the expression must parse thus:
(let x = True in (x == x)) == TrueHowever, implementations may well use a post-parsing pass to deal with fixities, so they may well incorrectly deliver the former parse. Programmers are advised to avoid constructs whose parsing involves an interaction of (lack of) associativity with the let/lambda meta-rule.
"As another example, the expression
(let x = 10 in x +)is invalid because, by the let/lambda meta-rule (Section 3) the expression
(let n = 10 in n + x)parses as
(let n = 10 in (n + x))rather than
((let n = 10 in n) + x)"
"It is a right-associative operator, with precedence level 5 (Section 4.4.2)."
(Otherwise this information is found only in the Prelude.)
A note about parsing. The (type-incorrect) expression
case x of { (a,_) | let b = not a in b :: Bool -> a }
is tricky to parse correctly. It has a single unambiguous parse, namely
case x of { (a,b) | (let b = not a in b :: Bool) -> a }
However, the phrase Bool -> a is syntactically valid as a type, and
parsers with limited lookahead may incorrectly commit to this choice, and hence
reject the program. Programmers are advised, therefore, to avoid guards that
end with a type signature --- indeed that is why a "gd" contains
an "exp^0" not an "exp".
stmts -> stmt1 ... stmtn exp [;] (n>=0)
The expression F {}, where F is a data constructor, is legal whether or not F was declared with record syntax, provided F has no strict fields; it denotes F _|_1 ... _|_n, where n is the arity of F.
(This matches the dual for pattern matching, in Section 4.2.1.)
f :: (Int,Int,Int) -> [Int] -> Int
f ~(x,y,z) [a] | (a == y) = 1
(The previous example use boolean and, which is non-strict in its second argument!)
case _|_ of { K x1 ... xn -> e; _ -> e' } = _|_
where K is a data constructor of arity n
class [scontext =>] simpleclass [where decls]by
class [scontext =>] tycls tyvar [where decls]
"These special syntactic forms always denote the built-in type constructors for functions, tuples, and lists, regardless of what is in scope. In a similar way, the prefix type constructors (->),, [], (), (,), and so on, always denote the built-in type constructors; they cannot be qualified, nor mentioned in import or export lists (Section 5). (Hence the special production, gtycon, above.)
"Although the tuple and list types have special syntax, their semantics is the same as the equivalent user-defined algebraic data types."
(This stuff is clarification only.)
"Pattern matching against ConsSet also gives rise to an Eq a constraint. For example:
f (ConsSet a s) = athe function f has inferred type Eq a => Set a -> a."
"The pattern "F {}" matches any value built with constructor F, whether or not F was declared with record syntax."
"Lexically, "!" is an ordinary varsym not a reservedop; it has special significance only in the context of the argument types of a data declaration."
idecl -> (funlhs | var) rhs(i.e. omitting the alternatives for "qvar" and "qfunlhs").
"It is illegal to give a binding for a class method that is not in scope, but the name under which it is in scope is immaterial; in particular, it may be a qualified name. (This rule is identical to that used for subordinate names in export lists --- Section 5.2.) For example, this is legal, even though return is in scope only with the qualified name Monad.return.
module A where
import qualified Monad
instance Monad.Monad T where
return = ...
(>>=) = ...
"
The new phrase is "if v appears only in constraints of the form (C v) where C is a class". Without this condition the rest of the sentence does not make sense.
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.)
f :: (Monad m, Eq (m a)) => a -> m a -> Bool
f x y = x == return y
is wrong; it should read
f x y = return x == y
"The usual Hindley-Milner restriction on polymorphism is that only type variables that do not occur free in the environment may be generalized."
(The sense was backward before.)
"There are two minor exceptions to this statement. First, default declarations scope over a single module (Section 4.3.4). Second, Rule 2 of the monomorphism restriction (Section 4.5.5) is affected by module boundaries."
This footnote qualifies the otherwise over-strong statement.
"In all cases, the (possibly-qualified) type constructor T must be in scope. The constructor and field names c_i in the second form are unqualified; one of these subordinate names is legal if and only if (a) it names a constructor or field of T, and (b) the constructor or field is in scope in the module body regardless of whether it is in scope under a qualified or unqualified name. For example, the following is legal
module A( Mb.Maybe( Nothing, Just ) ) where
import qualified Maybe as Mb
"
The form "module M" names the set of all entities that are in scope with both an unqualified name "e" and a qualified name "M.e". This set may be empty. For example:
module Queue( module Stack, enqueue, dequeue ) where
import Stack
...
"Here the module Queue uses the module name Stack in its export
list to abbreviate all the entities imported from Stack.
"A module can name its own local definitions in its export list using its own name in the `module M'' syntax, because a local declaration brings into scope both a qualified and unqualified name. For example:
module Mod1( module Mod1, module Mod2 ) where import Mod2 import Mod3"Here module Mod1 exports all local definitions as well as those imported from Mod2 but not those imported from Mod3." It is an error to use module M in an export list unless M is the module bearing the export list, or M is imported by at least one import declaration (qualified or unqualified).
"It makes no difference to an importing module how an entity was exported. For example, a field name f from data type T may be exported individually (f, item (1) above); or as an explicitly-named member of its data type (T(f), item (2)); or as an implicitly-named member (T(..) item(2)); or by exporting an entire module (module M, item (5)).
Exports lists are cumulative: the set of entities exported by an export list is the union of the entities exported by the individual items of the list.
The unqualified names of the entities exported by a module must all be distinct (within their respective namespace). For example
module A ( C.f, C.g, g, module B ) where -- an invalid module import B(f) import qualified C(f,g) g = f TrueThere are name clashes in the export list between C.g and g, and between module B and C.f (assuming B.f and C.f are different entities), even though there are no name clashes within module A itself.
"Lexically speaking, the terminal symbols "as", "qualified" and "hiding" are each a "varid" rather than a "reservedid". They have special significance only in the context of an import declaration; they may also be used as variables."
import Foo as A(f)
module M where
M.f x = ... -- ILLEGAL
g x = let M.y = x+1 in ... -- ILLEGAL
(This just clarifies that qualifiers aren't legal in local decls either.)
"The name occurring in a type signature or fixity declarations is always unqualified, and unambiguously refers to another declaration in the same declaration list (except that the fixity declaration for a class method can occur at top level --- Section 4.4.2). For example, the following module is legal:
module F where
sin :: Float -> Float
sin x = (x::Float)
f x = Prelude.sin (F.sin x)
The local declaration for sin is legal, even though
the Prelude function sin is implicitly in scope.
The references to
Prelude.sin and F.sin must both be qualified to make
it unambigous which sin is meant.
However, the unqualified name "sin" in the type
signature in the first line of F unambiguously refers to the
local declaration for sin."
"The Prelude module is imported automatically into all modules as if by the statement `import Prelude', if and only if it is not imported with an explicit import declaration. This provision for explicit import allows entities defined in the Prelude to be selectively imported, just like those from any other module."
module A( null, nonNull ) where
import Prelude hiding( null )
null, nonNull :: Int -> Bool
null x = x == 0
nonNull x = not (null x)
Module A redefines null, and contains an unqualified reference
to null on the right hand side of nonNull.
The latter would be ambiguous without the "hiding(null)" on the
"import Prelude" statement.
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.
"It is possible to construct and use a different module to serve in place of the Prelude. Other than the fact that it is implicitly imported, the Prelude is an ordinary Haskell module; it is special only in that some objects in the Prelude are referenced by special syntactic constructs. Redefining names used by the Prelude does not affect the meaning of these special constructs. For example, in
module B where
import Prelude()
import MyPrelude
f x = (x,x)
g x = (,) x x
h x = [x] ++ []
the explicit import Prelude() declaration prevents the automatic
import of Prelude, while the declaration import MyPrelude brings the
non-standard prelude into scope.
The special syntax for tuples (such as (x,x) and (,)) and lists
(such as [x] and []) continues to refer to the tuples and lists
defined by the standard Prelude;
there is no way to redefine the meaning of [x], for example, in terms of a
different implementation of lists.
On the other hand, the use of ++ is not special syntax, so it refers
to ++ imported from MyPrelude.
"It is not possible, however, to hide instance declarations in the Prelude. For example, one cannot define a new instance for Show Char."
"Tuples are algebraic datatypes with special syntax, as defined in Section 3.8. Each tuple type has a single constructor. All tuples are instances of Eq, Ord, Bounded, Read, Show (provided, of course, that all their component types are).
There is no upper bound on the size of a tuple, but some Haskell implementations may restrict the size of tuples, and limit the instances associated with larger tuples. However, every Haskell implementation must support tuples up to size 15, together with their instances for Eq, Ord, Bounded, Read, and Show. The Prelude and libraries define tuple functions such as zip for tuples up to a size of 7."
max x y | x <= y = y
| otherwise = x
min x y | x <= y = x
| otherwise = y
(This change aligns the report with the code given in the Appendix.)
"The function lex :: ReadS String, used by read, is also part of the Prelude. It reads a single lexeme from the input, discarding initial white space, and returning the characters that constitute the lexeme. If the input string contains only white space, lex returns a single successful ``lexeme'' consisting of the empty string. (Thus lex "" = [("","")].) If there is no legal lexeme at the beginning of the input string, lex fails (i.e. returns [])."
fromRealFrac :: (RealFrac a, Fractional b) => a -> b
should be replaced by
realToFrac :: (Real a, Fractional b) => a -> b
(The "(positive)" clarifies a slightly ambiguous point, while the specification for gcd 0 0 remains controversial. There was a lot of email on the Haskell mailing list in Dec 2001 about the latter point.)
userError :: String -> IOErrorAlso 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)
"
"The default method definitions, given with class declarations, constitute a specification only of the default method. They do not constitute a specification of the meaning of the method in all instances. To take one particular example, the default method for enumFrom in class Enum will not work properly for types whose range exceeds that of Int (because fromEnum cannot map all values in the type to distinct Int values)."
"To reduce the occurrence of unexpected ambiguity errors, and to improve efficiency, a number of commonly-used functions over lists use the Int type rather than using a more general numeric type, such as Integral a or Num a. These functions are: take, drop, index, length, splitAt, and replicate. The more general versions are given in the List library, with the prefix "generic"; for example genericLength."
-- The (:) operator is built-in syntax, and cannot legally be given -- a fixtity declaration; but its fixity is given by: -- infixr 5 :
-- NOTE: these default methods only make sense for types -- that map injectively into Int using fromEnum -- and toEnum.
enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]
maxBound = primUnicodeMaxChar
fail s = ioError (userError s)
numericEnumFromThenTo n n' m = takeWhile p (numericEnumFromThen n n')
where
p | n' >= n = (<= m + (n'-n)/2)
| otherwise = (>= m + (n'-n)/2)
(This change makes the code agree with the last bullet in (the revised version of) 6.3.4.)
map :: (a -> b) -> [a] -> [b]
-- List index (subscript) operator, 0-origin
(!!) :: [a] -> Int -> a
xs !! n | n < 0 = error "Prelude.!!: negative index"
[] !! _ = error "Prelude.!!: index too large"
(x:_) !! 0 = x
(_:xs) !! n = xs !! (n-1)
(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 (n-1) xs
drop :: Int -> [a] -> [a]
drop n xs | n <= 0 = xs
drop _ [] = []
drop n (_:xs) = drop (n-1) 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.
lexFracExp s = [("",s)]
to read instead
lexFracExp s = lexExp s
(This change allows 10e3 to be a single lexeme; c.f. the lexical change on page 7.)
instance Show Int where
showsPrec n = showsPrec n . toInteger
-- Converting to Integer avoids
-- possible difficulty with minInt
instance Read Int where
readsPrec p r = [(fromInteger i, t) | (i,t) <- readsPrec p r]
-- Reading at the Integer type avoids
-- possible difficulty with minInt
The previous definitions (which are simply specifications, remember) failed on minInt.
instance Read Float where
readsPrec p = readSigned readFloat
instance Read Double where
readsPrec p = readSigned readFloat
(Adding the 'readSigned' call.)
interact :: (String -> String) -> IO ()
-- The hSetBuffering ensures the expected interactive behaviour
interact f = do hSetBuffering stdin NoBuffering
hSetBuffering stdout NoBuffering
s <- getContents
putStr (f s)
"If a let, where, do,, or of keyword is not followed by the lexeme {, the token "{n}" is inserted after the keyword, where "n" is the indentation of the next lexeme if there is one, or "0" if the end of file has been reached."
(This addresses the question of end of file just after a where.)
"Where the start of a token is preceded only by white space on same line, this token is preceded by "<n>" where "n" is the indentation of the token, provided that it is not, as a consequence of the first two rules, preceded by "{n}".
(This addresses the question of empty lines (no layout token) and string-gap tokens (no layout token in the middle of them). I have added a clarifying example as well.)
"However, to avoid visual confusion, programmers should avoid writing programs in which the meaning of implicit layout depends on the width of non-space characters."
| L (<n>:ts) (m:ms) | = | ; : (L ts (m:ms)) | if m = n |
| = | } : (L (<n>:ts) ms) | if n < m | |
| L (<n>:ts) ms | = | L ts ms | |
| L ({n}:ts) (m:ms) | = | { : (L ts (n:m:ms)) | if n > m (Note 1) |
| L ({n}:ts) [] | = | { : (L ts [n]) | if n > 0 (Note 1) |
| L ({n}:ts) ms | = | { : } : (L (<n>:ts) ms) | (Note 2) |
| L (}:ts) (0:ms) | = | } : (L ts ms) | (Note 3) |
| L (}:ts) ms | = | parse-error | (Note 3) |
| L ({:ts) ms | = | { : (L ts (0:ms)) | (Note 4) |
| L (t:ts) (m:ms) | = | } : (L (t:ts) ms) | if m /= 0 and parse-error(t) |
| (Note 5) | |||
| L (t:ts) ms | = | t : (L ts ms) | |
| L [] [] | = | [] | |
| L [] (m:ms) | = | } : L [] ms | if m /=0 (Note 6) |
"The parse-error rule is hard to implement in its full generality, because doing so involves fixities. For example, the expression
do a == b == chas a single unambiguous (albeit probably type-incorrect) parse, namely
(do { a == b }) == c
because (==) is non-associative. Programmers are therefore advised to avoid
writing code that requires the parser to insert a closing brace in such
situations."
"The program text is recovered by taking only those lines beginning with ">", and replacing the leading ">" with a space."
"More precisely:
All derived operations of class Eq and Ord are strict in both arguments. For example, False <= _|_ is _|_ , even though False is the first constructor of the Bool type.
(The old, stronger, equation is simply false.)
"readsPrec will parse any valid representation of the standard types apart from strings, for which only quoted strings are accepted, and other lists, for which only the bracketed form [...] is accepted."
The result of show is a syntactically correct Haskell expression containing only constants, given the fixity declarations in force at the point where the type is declared. It contains only the constructor names defined in the data type, parentheses, and spaces. When labelled constructor fields are used, braces, commas, field names, and equal signs are also used. Parentheses are only added where needed, ignoring associativity. No line breaks are added. The result of show is readable by read if all component types are readable. (This is true for all instances defined in the Prelude but may not be true for user-defined instances.)
Derived instances of Read make the following assumptions, which derived instances of Show obey:
infixr :$ data T = Int :$ T | NTthen:
"The INLINE pragma instructs the compiler to inline the specified variables at their use sites. Compilers will often automatically inline simple expressions. This may be prevented by the NOINLINE pragma."
foldl (+) 0 [a,b,c] = ((0+a)+b)+c
foldr (+) 0 [a,b,c] = a+(b+(c+0))
Furthermore, the function name was misspelled in the equation for foldr1.
"Copyright (c) Simon Peyton Jones.
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 Haskell 98 libraries."
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.
succ x = x+1
pred x = x-1
(This makes succ/pred behave in the same way for Ratio as they do for Float and Double.
Of course, it is still highly dubious having these fractional types in Enum at all,
but that is another matter.)
instance (Read a, Integral a) => Read (Ratio a) where
readsPrec p = readParen (p > prec)
(\r -> [(x%y,u) | (x,s) <- readsPrec (prec+1) r,
("%",t) <- lex s,
(y,u) <- readsPrec (prec+1) t ])
instance (Integral a) => Show (Ratio a) where
showsPrec p (x:%y) = showParen (p > prec)
(showsPrec (prec+1) x .
showString " % " .
showsPrec (prec+1) y)
(It is important that the recursive calls carry the appropriate precedence.)
showSigned :: Real a => (a -> ShowS) -> Int -> a -> ShowS
showSigned showPos p x
| x < 0 = showParen (p > 6) (showChar '-' . showPos (-x))
| otherwise = showPos x
-- showInt, showOct, showHex are used for positive numbers only
showInt, showOct, showHex :: Integral a => a -> ShowS
showOct = showIntAtBase 8 intToDigit
showInt = showIntAtBase 10 intToDigit
showHex = showIntAtBase 16 intToDigit
showIntAtBase :: Integral a
=> a -- base
-> (Int -> Char) -- digit to char
-> a -- number to show
-> ShowS
showIntAtBase base intToDig n rest
| n < 0 = error "Numeric.showIntAtBase: can't show negative numbers"
| n' == 0 = rest'
| otherwise = showIntAtBase base intToDig n' rest'
where
(n',d) = quotRem n base
rest' = intToDig (fromIntegral d) : rest
(This siginficant change extends the Numeric library so that it can show
octal and hexadecimal numbers, just as it can already read them.)
FFFixed ->
case decs of
Nothing -- Always prints a decimal point
| e > 0 -> take e (ds ++ repeat '0')
++ '.' : mk0 (drop e ds)
| otherwise -> "0." ++ mk0 (replicate (-e) '0' ++ ds)
Just dec -> -- Print decimal point iff dec > 0
let dec' = max dec 0 in
if e >= 0 then
let (ei, is') = roundTo base (dec' + e) is
(ls, rs) = splitAt (e+ei)
(map intToDigit is')
in mk0 ls ++ mkdot0 rs
else
let (ei, is') = roundTo base dec'
(replicate (-e) 0 ++ is)
d : ds = map intToDigit
(if ei > 0 then is' else 0:is')
in d : mkdot0 ds
where
mk0 "" = "0" -- Print 0.34, not .34
mk0 s = s
mkdot0 "" = "" -- Print 34, not 34.
mkdot0 s = '.' : s -- when the format specifies no
-- digits after the decimal point
(This fixes an infinite loop.)
++ [ (0/0, t) | ("NaN",t) <- lex r]
++ [ (1/0, t) | ("Infinity",t) <- lex r]
(This makes readFloat able to read "Infinity" and "NaN", which formatRealFloat
can produce.)
map index (range (l,u)) == [0..rangeSize (l,u)]This documents an invariant that was previously only implicit.
class Ord a => Ix a where
range :: (a,a) -> [a]
index :: (a,a) -> a -> Int
inRange :: (a,a) -> a -> Bool
rangeSize :: (a,a) -> Int
class Ord a => Ix a where
range :: (a,a) -> [a]
index :: (a,a) -> a -> Int
inRange :: (a,a) -> a -> Bool
rangeSize :: (a,a) -> Int
rangeSize b@(l,h) | null (range b) = 0
| otherwise = index b h + 1
-- 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)) = []
(Note: the comment has changed too; it was misleading before.)
"It is possible to derive an instance of Ix automatically, using a deriving clause on a data declaration (Section 4.3.3 of the Language Report). Such derived instance declarations for the class Ix are only possible for enumerations (i.e. datatypes having only nullary constructors) and single-constructor datatypes, whose constituent types are instances of Ix. A Haskell implementation must provide Ix instances for tuples up to at least size 15."
[This change just clarifies, and propagates the "instances up to size 15" change from Section 6.1.6 of the Language Report.]
instance (Ix a, Show a, Show b) => Show (Array a b) where
showsPrec p a = showParen (p > arrPrec) (
showString "array " .
showsPrec (arrPrec+1) (bounds a) . showChar ' ' .
showsPrec (arrPrec+1) (assocs a) )
instance (Ix a, Read a, Read b) => Read (Array a b) where
readsPrec p = readParen (p > arrPrec)
(\r -> [ (array b as, u)
| ("array",s) <- lex r,
(b,t) <- readsPrec (arrPrec+1) s,
(as,u) <- readsPrec (arrPrec+1) t ])
-- Precedence of the 'array' function is that of application itself
arrPrec = 10
(It is important that the recursive calls use the appropriate precedence.)
"The unfoldr function is a `dual' to foldr: while foldr reduces a list to a summary value, unfoldr builds a list from a seed value. For example:
iterate f == unfoldr (\x -> Just (x, f x))In some cases, unfoldr can undo a foldr operation:"
(Followed by the existing displayed equation.)
nub :: (Eq a) => [a] -> [a] nub [] = [] nub (x:xs) = x : nub (filter (\y -> not (x == y)) xs)(This eliminates a conflict with the definition in Section 7.8.)
unionBy eq xs ys = xs ++ deleteFirstsBy eq (nubBy eq ys) xs
(This is a simpler definition to understand.)
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.
lexLitChar ('\\':s) = map (prefix '\\') (lexEsc s)
where
lexEsc (c:s) | c `elem` "abfnrtv\\\"'" = [([c],s)]
lexEsc ('^':c:s) | c >= '@' && c <= '_' = [(['^',c],s)]
-- Numeric escapes
lexEsc ('o':s) = [prefix 'o' (span isOctDigit s)]
lexEsc ('x':s) = [prefix 'x' (span isHexDigit s)]
lexEsc s@(d:_) | isDigit d = [span isDigit s]
-- Very crude approximation to \XYZ.
lexEsc s@(c:_) | isUpper c = [span isCharName s]
lexEsc _ = []
isCharName c = isUpper c || isDigit c
prefix c (t,s) = (c:t, s)
(The effect is to allow octal and hexadecimal escapes in lexLitChar, just
as in readLitChar.)
try :: IO a -> IO (Either IOError a)
This change attempts to clarify the (murky) meaning of hGetContents followed by hClose.
"Implementations should enforce as far as possible, at least locally to the Haskell process, multiple-reader single-writer 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 semi-closed handle is managing a file for output, no new handle can be allocated for that file. If any open or semi-closed 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 implementation-dependent, 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 semi-closed 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."
"Performing hClose on a handle that has already been closed has no effect; doing so not an error. All other operations on a closed handle will fail. If hClose fails for any reason, any further operations (apart from hClose) on the handle will still fail as if "hdl" had been successfully closed."
(The significant change here is that it is not an error to hClose a handle twice.)
"The hGetLine fails with isEOFError if the end of file is encountered when reading the first character of the line. If hGetLine encounters end-of-file at any other point while reading in a line, it is treated as a line terminator and the (partial) line is returned."
where readNum :: IO Integer -- Need a type signature for readLn to avoid ambiguity readNum = readLn(This change merely advertises the generally useful function readLn.)
data Permissions
= Permissions {
readable, writable, executable, searchable :: Bool
}
deriving ( Eq, Ord, Read, Show )
"Each entry in the returned list is named relative to the directory dir, not as an absolute path."