2 % (c) The GRAP/AQUA Project, Glasgow University, 1992-1996
4 \section{Module @PrelShow@}
8 {-# OPTIONS -fno-implicit-prelude #-}
14 -- Instances for Show: (), [], Bool, Ordering, Int, Char
17 shows, showChar, showString, showParen, showList__, showSpace,
18 showLitChar, protectEsc,
19 intToDigit, showSignedInt,
21 -- Character operations
22 isAscii, isLatin1, isControl, isPrint, isSpace, isUpper,
23 isLower, isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
28 lines, unlines, words, unwords
32 import {-# SOURCE #-} PrelErr ( error )
36 import PrelList ( (!!), break, dropWhile
37 #ifdef USE_REPORT_PRELUDE
45 %*********************************************************
47 \subsection{The @Show@ class}
49 %*********************************************************
52 type ShowS = String -> String
55 showsPrec :: Int -> a -> ShowS
57 showList :: [a] -> ShowS
59 showsPrec _ x s = show x ++ s
61 showList ls s = showList__ shows ls s
63 showList__ :: (a -> ShowS) -> [a] -> ShowS
64 showList__ _ [] s = "[]" ++ s
65 showList__ showx (x:xs) s = '[' : showx x (showl xs)
68 showl (y:ys) = ',' : showx y (showl ys)
71 %*********************************************************
73 \subsection{Simple Instances}
75 %*********************************************************
79 instance Show () where
80 showsPrec _ () = showString "()"
82 instance Show a => Show [a] where
83 showsPrec _ = showList
85 instance Show Bool where
86 showsPrec _ True = showString "True"
87 showsPrec _ False = showString "False"
89 instance Show Ordering where
90 showsPrec _ LT = showString "LT"
91 showsPrec _ EQ = showString "EQ"
92 showsPrec _ GT = showString "GT"
94 instance Show Char where
95 showsPrec _ '\'' = showString "'\\''"
96 showsPrec _ c = showChar '\'' . showLitChar c . showChar '\''
98 showList cs = showChar '"' . showl cs
99 where showl "" s = showChar '"' s
100 showl ('"':xs) s = showString "\\\"" (showl xs s)
101 showl (x:xs) s = showLitChar x (showl xs s)
102 -- Making 's' an explicit parameter makes it clear to GHC
103 -- that showl has arity 2, which avoids it allocating an extra lambda
104 -- The sticking point is the recursive call to (showl xs), which
105 -- it can't figure out would be ok with arity 2.
107 instance Show Int where
108 showsPrec p n = showSignedInt p n
110 instance Show a => Show (Maybe a) where
111 showsPrec _p Nothing s = showString "Nothing" s
112 showsPrec p@(I# p#) (Just x) s
113 = (showParen (p# >=# 10#) $
115 showsPrec (I# 10#) x) s
117 instance (Show a, Show b) => Show (Either a b) where
118 showsPrec p@(I# p#) e s =
119 (showParen (p# >=# 10#) $
121 Left a -> showString "Left " . showsPrec (I# 10#) a
122 Right b -> showString "Right " . showsPrec (I# 10#) b)
128 %*********************************************************
130 \subsection{Show instances for the first few tuples
132 %*********************************************************
135 -- The explicit 's' parameters are important
136 -- Otherwise GHC thinks that "shows x" might take a lot of work to compute
137 -- and generates defns like
138 -- showsPrec _ (x,y) = let sx = shows x; sy = shows y in
139 -- \s -> showChar '(' (sx (showChar ',' (sy (showChar ')' s))))
141 instance (Show a, Show b) => Show (a,b) where
142 showsPrec _ (x,y) s = (showChar '(' . shows x . showChar ',' .
143 shows y . showChar ')')
146 instance (Show a, Show b, Show c) => Show (a, b, c) where
147 showsPrec _ (x,y,z) s = (showChar '(' . shows x . showChar ',' .
148 shows y . showChar ',' .
149 shows z . showChar ')')
152 instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where
153 showsPrec _ (w,x,y,z) s = (showChar '(' . shows w . showChar ',' .
154 shows x . showChar ',' .
155 shows y . showChar ',' .
156 shows z . showChar ')')
159 instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) where
160 showsPrec _ (v,w,x,y,z) s = (showChar '(' . shows v . showChar ',' .
161 shows w . showChar ',' .
162 shows x . showChar ',' .
163 shows y . showChar ',' .
164 shows z . showChar ')')
169 %*********************************************************
171 \subsection{Support code for @Show@}
173 %*********************************************************
176 shows :: (Show a) => a -> ShowS
177 shows = showsPrec zeroInt
179 showChar :: Char -> ShowS
182 showString :: String -> ShowS
185 showParen :: Bool -> ShowS -> ShowS
186 showParen b p = if b then showChar '(' . p . showChar ')' else p
189 showSpace = {-showChar ' '-} \ xs -> ' ' : xs
192 Code specific for characters
195 showLitChar :: Char -> ShowS
196 showLitChar c | c > '\DEL' = \s -> showChar '\\' (protectEsc isDigit (shows (ord c)) s)
197 showLitChar '\DEL' = showString "\\DEL"
198 showLitChar '\\' = showString "\\\\"
199 showLitChar c | c >= ' ' = showChar c
200 showLitChar '\a' = showString "\\a"
201 showLitChar '\b' = showString "\\b"
202 showLitChar '\f' = showString "\\f"
203 showLitChar '\n' = showString "\\n"
204 showLitChar '\r' = showString "\\r"
205 showLitChar '\t' = showString "\\t"
206 showLitChar '\v' = showString "\\v"
207 showLitChar '\SO' = \s -> protectEsc (== 'H') (showString "\\SO") s
208 showLitChar c = \s -> showString ('\\' : asciiTab!!ord c) s
209 -- The "\s ->" here means that GHC knows it's ok to put the
210 -- asciiTab!!ord c inside the lambda. Otherwise we get an extra
211 -- lambda allocated, and that can be pretty bad
213 protectEsc :: (Char -> Bool) -> ShowS -> ShowS
214 protectEsc p f = f . cont
215 where cont s@(c:_) | p c = "\\&" ++ s
218 intToDigit :: Int -> Char
220 | i >=# 0# && i <=# 9# = unsafeChr (ord '0' `plusInt` I# i)
221 | i >=# 10# && i <=# 15# = unsafeChr (ord 'a' `plusInt` I# i `minusInt` I# 10#)
222 | otherwise = error ("Char.intToDigit: not a digit " ++ show (I# i))
226 Code specific for Ints.
229 showSignedInt :: Int -> Int -> ShowS
230 showSignedInt (I# p) (I# n) r
231 | n <# 0# && p ># 6# = '(':itos n (')':r)
232 | otherwise = itos n r
234 itos :: Int# -> String -> String
236 | n >=# 0# = itos' n r
237 | negateInt# n <# 0# = -- n is minInt, a difficult number
238 itos (n `quotInt#` 10#) (itos' (negateInt# (n `remInt#` 10#)) r)
239 | otherwise = '-':itos' (negateInt# n) r
241 itos' :: Int# -> String -> String
244 | x <# 10# = C# (chr# (x +# ord# '0'#)) : cs
245 | otherwise = itos' (x `quotInt#` 10#)
246 (C# (chr# (x `remInt#` 10# +# ord# '0'#)) : cs)
249 %*********************************************************
251 \subsection{Character stuff}
253 %*********************************************************
256 isAscii, isLatin1, isControl, isPrint, isSpace, isUpper,
257 isLower, isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum :: Char -> Bool
258 isAscii c = c < '\x80'
259 isLatin1 c = c <= '\xff'
260 isControl c = c < ' ' || c >= '\DEL' && c <= '\x9f'
261 isPrint c = not (isControl c)
263 -- isSpace includes non-breaking space
264 -- Done with explicit equalities both for efficiency, and to avoid a tiresome
265 -- recursion with PrelList elem
266 isSpace c = c == ' ' ||
274 -- The upper case ISO characters have the multiplication sign dumped
275 -- randomly in the middle of the range. Go figure.
276 isUpper c = c >= 'A' && c <= 'Z' ||
277 c >= '\xC0' && c <= '\xD6' ||
278 c >= '\xD8' && c <= '\xDE'
279 -- The lower case ISO characters have the division sign dumped
280 -- randomly in the middle of the range. Go figure.
281 isLower c = c >= 'a' && c <= 'z' ||
282 c >= '\xDF' && c <= '\xF6' ||
283 c >= '\xF8' && c <= '\xFF'
284 isAsciiLower c = c >= 'a' && c <= 'z'
285 isAsciiUpper c = c >= 'A' && c <= 'Z'
287 isAlpha c = isLower c || isUpper c
288 isDigit c = c >= '0' && c <= '9'
289 isOctDigit c = c >= '0' && c <= '7'
290 isHexDigit c = isDigit c || c >= 'A' && c <= 'F' ||
292 isAlphaNum c = isAlpha c || isDigit c
294 -- Case-changing operations
296 toUpper, toLower :: Char -> Char
298 | isAsciiLower c = C# (chr# (ord# c# -# 32#))
300 -- fall-through to the slower stuff.
301 | isLower c && c /= '\xDF' && c /= '\xFF'
302 = unsafeChr (ord c `minusInt` ord 'a' `plusInt` ord 'A')
309 | isAsciiUpper c = C# (chr# (ord# c# +# 32#))
311 | isUpper c = unsafeChr (ord c `minusInt` ord 'A' `plusInt` ord 'a')
315 asciiTab = -- Using an array drags in the array module. listArray ('\NUL', ' ')
316 ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
317 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
318 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
319 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
323 %*********************************************************
325 \subsection{Functions on strings}
327 %*********************************************************
329 lines breaks a string up into a list of strings at newline characters.
330 The resulting strings do not contain newlines. Similary, words
331 breaks a string up into a list of words, which were delimited by
332 white space. unlines and unwords are the inverse operations.
333 unlines joins lines with terminating newlines, and unwords joins
334 words with separating spaces.
337 lines :: String -> [String]
339 lines s = let (l, s') = break (== '\n') s
344 words :: String -> [String]
345 words s = case dropWhile {-partain:Char.-}isSpace s of
349 break {-partain:Char.-}isSpace s'
351 unlines :: [String] -> String
352 #ifdef USE_REPORT_PRELUDE
353 unlines = concatMap (++ "\n")
355 -- HBC version (stolen)
356 -- here's a more efficient version
358 unlines (l:ls) = l ++ '\n' : unlines ls
361 unwords :: [String] -> String
362 #ifdef USE_REPORT_PRELUDE
364 unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
366 -- HBC version (stolen)
367 -- here's a more efficient version
370 unwords (w:ws) = w ++ ' ' : unwords ws