Commit ab3899f5 authored by Simon Peyton Jones's avatar Simon Peyton Jones
Browse files

Mainly Enum

parent 2e4b0e94
......@@ -577,6 +577,17 @@ to and from strings." add the sentence:
precedence of the enclosing context (see Appendix D.4)."
(Clarification only.)
<p><li> [Nov 2001] <strong> Page 79, Section 6.3.4, Class Enum;
Page 19, Section 3.10 Arithmetic Sequences; and Appendix D.2, Derived instances of Enum.</strong>
<ul>
<li> Move the specification of the <tt>Int</tt> and <tt>Integer</tt> instances of
<tt>Enum</tt> 3.10 to 6.3.4.
<li> Specify that, for bounded types, <tt>succ</tt> and <tt>pred</tt> should fail
when applied to <tt>maxBound</tt> and <tt>minBound</tt> resp.
<li> Specify that the <tt>enum</tt> functions on numeric types are strict.
<li> Remove material from D.2 so that it describes only the derived instances.
</ul>
<p><li><strong>Page 80, Section 6.3.6, Class Monad.</strong>
Right at the bottom of the page, replace "However, for IO, the fail
method invokes error." by "For IO, the fail method raises a user
......@@ -855,30 +866,38 @@ doing it by hand. In particular, an error will be raised if y is zero.
<ul>
<li> Add specifications for the functions exported by the Numeric library.
<p><li>In <tt>formatRealFloat</tt>, add the following local definitions:
<p><li>In <tt>formatRealFloat</tt>, replace the entire case alternative
starting <tt>FFFixed</tt> with the following:
<pre>
mk0 "" = "0" -- Used to ensure we print 34.0, not 34.
mk0 s = s -- and 0.34 not .34
mkdot0 "" = "" -- Used to ensure we print 34, not 34.
mkdot0 s = '.' : s
</pre>
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
<li> In the definition of <tt>formatRealFloat</tt>,
<ul>
<li> in the definition of <tt>doFmt</tt>,
<li> in the <tt>FFFixed</tt> branch of "<tt>case fmt of ...</tt>",
<li> in the <tt>Nothing</tt> branch of "<tt>case decs of ...</tt>",
replace the entire branch "<tt>Nothing -> ...</tt>" with
<pre>
Nothing | e >= 0 -> take e (ds ++ repeat '0') ++ mkdot0 (drop e ds)
| otherwise -> '0' : mkdot0 (replicate (-e) '0' ++ ds)
mkdot0 "" = "" -- Print 34, not 34.
mkdot0 s = '.' : s -- when the format specifies no
-- digits after the decimal point
</pre>
<li> in the <tt>Just dec</tt> branch, replace "<tt>(if null ls then "0" else ls) ++ (if null rs then "" else '.' : rs)</tt>"
by "<tt>mk0 ls ++ mkdot0 rs</tt>".
<li> also in the <tt>Just dec</tt> branch, replace "<tt>d : '.' : ds</tt>" by "<tt>d : mkdot0 ds</tt>".
</ul>
(This fixes an infinite loop.)
<p><li>In the definition of <tt>k</tt> in <tt>floatToDigits</tt> replace "<tt>fromInt e</tt>" by "<tt>fromIntegral e</tt>".
(<tt>fromInt</tt> no longer exists.)
......
......@@ -6,9 +6,10 @@ module Numeric(fromRat,
showEFloat, showFFloat, showGFloat, showFloat,
readFloat, lexDigits) where
import Char
import Ratio
import Array
import Char ( isDigit, isOctDigit, isHexDigit
, digitToInt, intToDigit )
import Ratio ( (%), numerator, denominator )
import Array ( (!), Array, array )
-- This converts a rational to a floating. This should be used in the
-- Fractional instances of Float and Double.
......@@ -116,7 +117,7 @@ readInt radix isDig digToInt s =
-- Unsigned readers for various bases
readDec, readOct, readHex :: (Integral a) => ReadS a
readDec = readInt 10 isDigit digitToInt
readDec = readInt 10 isDigit digitToInt
readOct = readInt 8 isOctDigit digitToInt
readHex = readInt 16 isHexDigit digitToInt
......@@ -149,12 +150,6 @@ formatRealFloat fmt decs x
else
doFmt fmt (floatToDigits (toInteger base) x)
mk0 "" = "0" -- Used to ensure we print 34.0, not 34.
mk0 s = s -- and 0.34 not .34
mkdot0 "" = "" -- Used to ensure we print 34, not 34.
mkdot0 s = '.' : s
doFmt fmt (is, e)
= let
ds = map intToDigit is
......@@ -183,12 +178,12 @@ formatRealFloat fmt decs x
FFFixed ->
case decs of
Nothing
Nothing -- Always prints a decimal point
| e > 0 -> take e (ds ++ repeat '0')
++ mkdot0 (drop e ds)
| otherwise -> '0' : mkdot0 (replicate (-e) '0' ++ ds)
++ '.' : mk0 (drop e ds)
| otherwise -> "0." ++ mk0 (replicate (-e) '0' ++ ds)
Just dec ->
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
......@@ -201,6 +196,14 @@ formatRealFloat fmt decs x
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
roundTo :: Int -> Int -> [Int] -> (Int, [Int])
roundTo base d is = case f d is of
......
%
% $Header: /home/cvs/root/haskell-report/report/basic.verb,v 1.9 2001/10/02 09:09:26 simonpj Exp $
% $Header: /home/cvs/root/haskell-report/report/basic.verb,v 1.10 2001/11/02 16:26:48 simonpj Exp $
%
%**<title>The Haskell 98 Report: Basic Types and Classes</title>
%*section 6
......@@ -61,8 +61,9 @@ characters is defined in Section~\ref{lexemes-char}; character
literals are nullary constructors in the datatype @Char@. Type @Char@
is an instance of the classes @Read@, @Show@, @Eq@, @Ord@,
@Enum@, and @Bounded@. The @toEnum@ and @fromEnum@ functions,
standard functions over bounded enumerations, map characters onto
@Int@ values in the range "[ 0 , 2^{16}-1 ]".
standard functions from class @Enum@, map characters to and from the
@Int@ type.
% @Int@ values in the range "[ 0 , 2^{16}-1 ]".
Note that ASCII control characters each have several representations
in character literals: numeric escapes, ASCII mnemonic escapes,
......@@ -445,6 +446,7 @@ input from a string, which must be completely consumed by the input
process. The @lex@ function used by @read@ is also part of the Prelude.
\subsubsection{The Enum Class}
\label{enum-class}
\indexclass{Enum}
\indextt{toEnum}
\indextt{fromEnum}
......@@ -469,20 +471,88 @@ class Enum a where
Class @Enum@ defines operations on sequentially ordered types.
The functions @succ@ and @pred@ return the successor and predecessor,
respectively, of a value.
The @toEnum@ and @fromEnum@ functions map values from a type in
@Enum@ onto @Int@. These functions are not meaningful for all
instances of @Enum@: floating
point values or @Integer@ may not be mapped onto an @Int@. A
runtime error occurs if either @toEnum@ or @fromEnum@ is given a value
not mappable to the result type.
The functions @fromEnum@ and @toEnum@ map values from a type in
@Enum@ to and from @Int@.
The @enumFrom@... methods are used when translating arithmetic
sequences (Section~\ref{arithmetic-sequences}), and should
obey the specification given in there.
sequences (Section~\ref{arithmetic-sequences}).
Instances of @Enum@ may be derived for any enumeration type (types
whose constructors have no fields); see Appendix~\ref{derived-appendix}.
For any type that is an instance of class @Bounded@, the following
should hold:
\begin{itemize}
\item The calls @succ maxBound@ and @pred minBound@ should result in
a runtime error.
\item @fromEnum@ and @toEnum@ should give a runtime error if the
result value is not representable in the result type. For example,
@toEnum 7 :: Bool@ is an error.
Instances of @Enum@ may be derived
for any enumeration type (types whose constructors have no fields).
There are also @Enum@ instances for floats.
\item @enumFrom@ and @enumFromThen@ should be defined with
an implicit bound, thus:
\bprog
@
enumFrom x = enumFromTo x maxBound
enumFromThen x y = enumFromThenTo x y bound
where
bound = if fromEnum y >= fromEnum x then
maxBound
else
minBound
@
\eprog
\end{itemize}
The following @Prelude@ types are instances of @Enum@:
\begin{itemize}
\item Enumeration types: @()@, @Bool@, and @Ordering@. The
semantics of these instances is given by Appendix~\ref{derived-appendix}.
For example, @[LT..]@ is the list @[LT,EQ,GT]@.
\item @Char@: the instance is given in Appendix~\ref{stdprelude}, based
on the primitive functions that convert between a @Char@ and an @Int@.
For example, @enumFromTo 'a' 'z'@ denotes
the list of lowercase letters in alphabetical order.
\item Numeric types: @Int@, @Integer@, @Float@, @Double@. The semantics
of these instances is given next.
\end{itemize}
For all four numeric types, @succ@ adds 1; and @pred@ subtracts 1.
The conversions @fromEnum@ and @toEnum@ convert between the type and @Int@.
in the case of @Float@ and @Double@, the digits after the decimal point may be lost.
It is implementation-dependent what @fromEnum@ returns when applied to
a value that is too large to fit in an @Int@.
For the types @Int@ and @Integer@, the enumeration functions
have the following meaning:
\begin{itemize}
\item The sequence "@enumFrom@~e_1" is the list "@[@e_1@,@e_1+1@,@e_1+2@,@...@]@".
\item The sequence "@enumFromThen@~e_1~e_2@" is the list "@[@e_1@,@e_1+i@,@e_1+2i@,@...@]@",
where the increment, "i", is "e_2-e_1". The increment may be zero or negative.
If the increment is zero, all the list elements are the same.
\item The sequence "@enumFromTo@~e_1~e_3" is
the list "@[@e_1@,@e_1+1@,@e_1+2@,@...e_3@]@".
The list is empty if "e_1 > e_3".
\item The sequence "@enumFromThenTo~e_1~e_2~e_3"
is the list "@[@e_1@,@e_1+i@,@e_1+2i@,@...e_3@]@",
where the increment, "i", is "e_2-e_1". If the increment
is positive or zero, the list terminates when the next element would
be greater than "e_3"; the list is empty if "e_1 > e_3".
If the increment is negative, the list terminates when the next element would
be less than "e_3"; the list is empty if "e1 < e_3".
\end{itemize}
For @Float@ and @Double@, the semantics of the @enumFrom@ family is
given by the rules for @Int@ above, except that the list terminates
when the elements become greater than "e_3+i/2" for positive increment
"i", or when they become less than "e_3+i/2" for negative "i".
@fromEnum@ and @toEnum@ convert between the type and @Int@.
For all four of these Prelude numeric types, all of the @enumFrom@
family of functions are strict in all their arguments.
\subsubsection{Class @Functor@}
\indexclass{Functor}
......
%
% $Header: /home/cvs/root/haskell-report/report/derived.verb,v 1.6 2001/08/14 07:48:24 simonpj Exp $
% $Header: /home/cvs/root/haskell-report/report/derived.verb,v 1.7 2001/11/02 16:26:48 simonpj Exp $
%
% The paragraph describing the formats of standard representations might
% be deleted, since the info is already in the Prelude.
......@@ -159,18 +159,7 @@ These examples illustrate this property:
\subsection{Derived instances of @Enum@}
\indexdi{Enum}
Derived instance declarations for the class @Enum@ are only
possible for enumerations.
@Enum@ introduces the class methods
@succ@\indextt{succ},
@pred@\indextt{pred},
@toEnum@\indextt{toEnum},
@fromEnum@\indextt{fromEnum},
@enumFrom@\indextt{enumFrom},
@enumFromThen@\indextt{enumFromThen},
@enumFromTo@\indextt{enumFromTo}, and
@enumFromThenTo@\indextt{enumFromThenTo}.
The latter four are used to define arithmetic sequences as described
in Section~\ref{arithmetic-sequences}.
possible for enumerations (data types with only nullary constructors).
The nullary constructors are assumed to be
numbered left-to-right with the indices 0 through $n-1\/$.
......@@ -180,18 +169,21 @@ an error to apply @succ@ to the maximum element, or @pred@ to the minimum
element.
The @toEnum@ and @fromEnum@ operators map enumerated values to and
from the @Int@ type.
@enumFrom n@ returns a list corresponding to the complete enumeration
of @n@'s type starting at the value @n@.
Similarly, @enumFromThen n n'@ is the enumeration starting at @n@, but
with second element @n'@, and with subsequent elements generated at a
spacing equal to the difference between @n@ and @n'@.
@enumFromTo@ and @enumFromThenTo@ are as defined by the
default class methods
\index{default class method}
for @Enum@ (see Figure~\ref{standard-classes},
page~\pageref{standard-classes}).
from the @Int@ type; @toEnum@ raises a runtime error if the @Int@ argument
is not the index of one of the constructors.
The definitions of the remaining methods are
\bprog
@
enumFrom x = enumFrom x maxBound
enumFromThen x y = enumFromThenTo x y bound
where
bound | fromEnum y >= fromEnum x = maxBound
| otherwise = minBound
enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]
enumFromThenTo x y z = map toEnum [fromEnum x, fromEnum y .. fromEnum z]
@
\eprog
For example,
given the datatype:
\bprog
......
%
% $Header: /home/cvs/root/haskell-report/report/exps.verb,v 1.12 2001/11/01 13:43:43 simonpj Exp $
% $Header: /home/cvs/root/haskell-report/report/exps.verb,v 1.13 2001/11/02 16:26:48 simonpj Exp $
%
%*section 3
%**<title>The Haskell 98 Report: Expressions</title>
......@@ -607,54 +607,9 @@ are class methods in the class @Enum@ as defined in the Prelude
}
The semantics of arithmetic sequences therefore depends entirely
on the instance declaration for the type "t". We give here the
semantics for @Prelude@ types, and indications of the expected semantics
for other, user-defined, types.
For the types @Int@ and @Integer@, arithmetic sequences have the following
meaning:
\begin{itemize}
\item The sequence "@[@e_1@..]@" is the list "@[@e_1@,@e_1+1@,@e_1+2@,@...@]@".
\item The sequence "@[@e_1@,@e_2@..]@" is the list "@[@e_1@,@e_1+i@,@e_1+2i@,@...@]@",
where the increment, "i", is "e_2-e_1". The increment may be zero or negative.
If the increment is zero, all the list elements are the same.
\item The sequence "@[@e_1@..@e_3@]@" is the list "@[@e_1@,@e_1+1@,@e_1+2@,@...e_3@]@".
The list is empty if "e_1 > e_3".
\item The sequence "@[@e_1@,@e_2@..@e_3@]@"
is the list "@[@e_1@,@e_1+i@,@e_1+2i@,@...e_3@]@",
where the increment, "i", is "e_2-e_1". If the increment
is positive or zero, the list terminates when the next element would
be greater than "e_3"; the list is empty if "e_1 > e_3".
If the increment is negative, the list terminates when the next element would
be less than "e_3"; the list is empty if "e1 < e_3".
\end{itemize}
For other {\em discrete} @Prelude@ types "t" that
are instances of @Enum@, namely @()@, @Bool@, @Char@ and @Ordering@,
the semantics is given by mapping the "e_i" to @Int@ using @fromEnum@,
using the above rules, and then mapping back to "t" with @toEnum@.
Where the type is also an instance of class @Bounded@
and "e_3" is omitted, an implied "e_3" is added
of @maxBound@ (if the increment is positive) or @minBound@ (resp. negative).
For example, @['a'..'z']@ denotes
the list of lowercase letters in alphabetical order, and @[LT..]@ is the
list @[LT,EQ,GT]@.
For {\em continuous} @Prelude@ types that are instances of @Enum@,
namely @Float@ and @Double@, the semantics is given by the rules for @Int@,
except that the list terminates when the elements become greater than
"e_3+i/2" for positive increment "i", or when they become less than
"e_3+i/2" for negative "i".
See Figure~\ref{standard-classes}%
%*ignore
, page~\pageref{standard-classes}
%*endignore
and Section~\ref{derived-decls} for more details of which @Prelude@
type are in @Enum@.
on the instance declaration for the type "t".
Section~\ref{enum-class} for more details of which @Prelude@
type are in @Enum@ and their semantics.
\subsection{List Comprehensions}
......
%
% $Header: /home/cvs/root/haskell-report/report/preface-13.verb,v 1.10 2001/11/01 13:43:43 simonpj Exp $
% $Header: /home/cvs/root/haskell-report/report/preface-13.verb,v 1.11 2001/11/02 16:26:48 simonpj Exp $
%
%**<title>The Haskell 98 Report: Preface</title>
%*section
......@@ -147,8 +147,8 @@ and, like type signatures, bind to an entity rather than to its name.
Version~1.4 of the report made the following relatively minor changes to the
language:
\begin{itemize}
\item The character set has been changed to Unicode\index{Unicode
character set}.
\item The character set has been changed to
Unicode\index{Unicode character set}.
\item List comprehensions have been generalized to arbitrary
monads.\index{list comprehension}
\item Import and export of class methods and constructors is no longer
......@@ -298,7 +298,7 @@ Sandra Loosemore,
Pablo Lopez,
Olaf Lubeck,
Ian Lynagh,
Christian Maeder
Christian Maeder,
Ketil Malde,
Simon Marlow,
Michael Marte,
......
%
% $Header: /home/cvs/root/haskell-report/report/syntax-lexical.verb,v 1.5 2001/09/11 16:19:17 simonpj Exp $
% $Header: /home/cvs/root/haskell-report/report/syntax-lexical.verb,v 1.6 2001/11/02 16:26:48 simonpj Exp $
%
@@@
@@@
program -> \{ lexeme | whitespace \}
lexeme -> qvarid | qconid | qop | literal | special | reservedop | reservedid
......@@ -49,7 +49,7 @@ uniDigit -> \tr{any Unicode decimal digit}
octit -> @0@ | @1@ | ... | @7@
hexit -> digit | @A@ | ... | @F@ | @a@ | ... | @f@
@@@
@@@
\indexsyn{program}%
\indexsyn{lexeme}%
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment