4df43511ed7968fe057f41d3af8c0d0e3de1620a
[ghc-base.git] / GHC / Show.lhs
1 \begin{code}
2 {-# OPTIONS -fno-implicit-prelude #-}
3 -----------------------------------------------------------------------------
4 -- |
5 -- Module      :  GHC.Show
6 -- Copyright   :  (c) The University of Glasgow, 1992-2002
7 -- License     :  see libraries/base/LICENSE
8 -- 
9 -- Maintainer  :  cvs-ghc@haskell.org
10 -- Stability   :  internal
11 -- Portability :  non-portable (GHC Extensions)
12 --
13 -- The 'Show' class, and related operations.
14 --
15 -----------------------------------------------------------------------------
16
17 module GHC.Show
18         (
19         Show(..), ShowS,
20
21         -- Instances for Show: (), [], Bool, Ordering, Int, Char
22
23         -- Show support code
24         shows, showChar, showString, showParen, showList__, showSpace,
25         showLitChar, protectEsc, 
26         intToDigit, showSignedInt,
27         appPrec, appPrec1,
28
29         -- Character operations
30         asciiTab,
31   ) 
32         where
33
34 import {-# SOURCE #-} GHC.Err ( error )
35 import GHC.Base
36 import GHC.Enum
37 import Data.Maybe
38 import Data.Either
39 import GHC.List ( (!!),
40 #ifdef USE_REPORT_PRELUDE
41                 , concatMap, foldr1
42 #endif
43                 )
44 \end{code}
45
46
47
48 %*********************************************************
49 %*                                                      *
50 \subsection{The @Show@ class}
51 %*                                                      *
52 %*********************************************************
53
54 \begin{code}
55 type ShowS = String -> String
56
57 class  Show a  where
58     showsPrec :: Int -> a -> ShowS
59     show      :: a   -> String
60     showList  :: [a] -> ShowS
61
62     showsPrec _ x s = show x ++ s
63     show x          = shows x ""
64     showList ls   s = showList__ shows ls s
65
66 showList__ :: (a -> ShowS) ->  [a] -> ShowS
67 showList__ _     []     s = "[]" ++ s
68 showList__ showx (x:xs) s = '[' : showx x (showl xs)
69   where
70     showl []     = ']' : s
71     showl (y:ys) = ',' : showx y (showl ys)
72
73 appPrec, appPrec1 :: Int
74         -- Use unboxed stuff because we don't have overloaded numerics yet
75 appPrec = I# 10#        -- Precedence of application:
76                         --   one more than the maximum operator precedence of 9
77 appPrec1 = I# 11#       -- appPrec + 1
78 \end{code}
79
80 %*********************************************************
81 %*                                                      *
82 \subsection{Simple Instances}
83 %*                                                      *
84 %*********************************************************
85
86 \begin{code}
87  
88 instance  Show ()  where
89     showsPrec _ () = showString "()"
90
91 instance Show a => Show [a]  where
92     showsPrec _         = showList
93
94 instance Show Bool where
95   showsPrec _ True  = showString "True"
96   showsPrec _ False = showString "False"
97
98 instance Show Ordering where
99   showsPrec _ LT = showString "LT"
100   showsPrec _ EQ = showString "EQ"
101   showsPrec _ GT = showString "GT"
102
103 instance  Show Char  where
104     showsPrec _ '\'' = showString "'\\''"
105     showsPrec _ c    = showChar '\'' . showLitChar c . showChar '\''
106
107     showList cs = showChar '"' . showl cs
108                  where showl ""       s = showChar '"' s
109                        showl ('"':xs) s = showString "\\\"" (showl xs s)
110                        showl (x:xs)   s = showLitChar x (showl xs s)
111                 -- Making 's' an explicit parameter makes it clear to GHC
112                 -- that showl has arity 2, which avoids it allocating an extra lambda
113                 -- The sticking point is the recursive call to (showl xs), which
114                 -- it can't figure out would be ok with arity 2.
115
116 instance Show Int where
117     showsPrec = showSignedInt
118
119 instance Show a => Show (Maybe a) where
120     showsPrec _p Nothing s = showString "Nothing" s
121     showsPrec p (Just x) s
122                           = (showParen (p > appPrec) $ 
123                              showString "Just " . 
124                              showsPrec appPrec1 x) s
125
126 instance (Show a, Show b) => Show (Either a b) where
127     showsPrec p e s =
128        (showParen (p > appPrec) $
129         case e of
130          Left  a -> showString "Left "  . showsPrec appPrec1 a
131          Right b -> showString "Right " . showsPrec appPrec1 b)
132        s
133 \end{code}
134
135
136 %*********************************************************
137 %*                                                      *
138 \subsection{Show instances for the first few tuples
139 %*                                                      *
140 %*********************************************************
141
142 \begin{code}
143 -- The explicit 's' parameters are important
144 -- Otherwise GHC thinks that "shows x" might take a lot of work to compute
145 -- and generates defns like
146 --      showsPrec _ (x,y) = let sx = shows x; sy = shows y in
147 --                          \s -> showChar '(' (sx (showChar ',' (sy (showChar ')' s))))
148
149 instance  (Show a, Show b) => Show (a,b)  where
150     showsPrec _ (x,y) s = (showChar '(' . shows x . showChar ',' .
151                                           shows y . showChar ')') 
152                           s
153
154 instance (Show a, Show b, Show c) => Show (a, b, c) where
155     showsPrec _ (x,y,z) s = (showChar '(' . shows x . showChar ',' .
156                                             shows y . showChar ',' .
157                                             shows z . showChar ')')
158                             s
159
160 instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where
161     showsPrec _ (w,x,y,z) s = (showChar '(' . shows w . showChar ',' .
162                                               shows x . showChar ',' .
163                                               shows y . showChar ',' .
164                                               shows z . showChar ')')
165                               s
166
167 instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) where
168     showsPrec _ (v,w,x,y,z) s = (showChar '(' . shows v . showChar ',' .
169                                                 shows w . showChar ',' .
170                                                 shows x . showChar ',' .
171                                                 shows y . showChar ',' .
172                                                 shows z . showChar ')') 
173                                 s
174 \end{code}
175
176
177 %*********************************************************
178 %*                                                      *
179 \subsection{Support code for @Show@}
180 %*                                                      *
181 %*********************************************************
182
183 \begin{code}
184 shows           :: (Show a) => a -> ShowS
185 shows           =  showsPrec zeroInt
186
187 showChar        :: Char -> ShowS
188 showChar        =  (:)
189
190 showString      :: String -> ShowS
191 showString      =  (++)
192
193 showParen       :: Bool -> ShowS -> ShowS
194 showParen b p   =  if b then showChar '(' . p . showChar ')' else p
195
196 showSpace :: ShowS
197 showSpace = {-showChar ' '-} \ xs -> ' ' : xs
198 \end{code}
199
200 Code specific for characters
201
202 \begin{code}
203 -- | Convert a character to a string using only printable characters,
204 -- using Haskell source-language escape conventions.  For example:
205 --
206 -- > showLitChar '\n' s  =  "\\n" ++ s
207 --
208 showLitChar                :: Char -> ShowS
209 showLitChar c s | c > '\DEL' =  showChar '\\' (protectEsc isDec (shows (ord c)) s)
210 showLitChar '\DEL'         s =  showString "\\DEL" s
211 showLitChar '\\'           s =  showString "\\\\" s
212 showLitChar c s | c >= ' '   =  showChar c s
213 showLitChar '\a'           s =  showString "\\a" s
214 showLitChar '\b'           s =  showString "\\b" s
215 showLitChar '\f'           s =  showString "\\f" s
216 showLitChar '\n'           s =  showString "\\n" s
217 showLitChar '\r'           s =  showString "\\r" s
218 showLitChar '\t'           s =  showString "\\t" s
219 showLitChar '\v'           s =  showString "\\v" s
220 showLitChar '\SO'          s =  protectEsc (== 'H') (showString "\\SO") s
221 showLitChar c              s =  showString ('\\' : asciiTab!!ord c) s
222         -- I've done manual eta-expansion here, becuase otherwise it's
223         -- impossible to stop (asciiTab!!ord) getting floated out as an MFE
224
225 isDec c = c >= '0' && c <= '9'
226
227 protectEsc :: (Char -> Bool) -> ShowS -> ShowS
228 protectEsc p f             = f . cont
229                              where cont s@(c:_) | p c = "\\&" ++ s
230                                    cont s             = s
231
232
233 asciiTab :: [String]
234 asciiTab = -- Using an array drags in the array module.  listArray ('\NUL', ' ')
235            ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
236             "BS",  "HT",  "LF",  "VT",  "FF",  "CR",  "SO",  "SI", 
237             "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
238             "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US", 
239             "SP"] 
240 \end{code}
241
242 Code specific for Ints.
243
244 \begin{code}
245 -- | Convert an 'Int' in the range @0@..@15@ to the corresponding single
246 -- digit 'Char'.  This function fails on other inputs, and generates
247 -- lower-case hexadecimal digits.
248 intToDigit :: Int -> Char
249 intToDigit (I# i)
250     | i >=# 0#  && i <=#  9# =  unsafeChr (ord '0' `plusInt` I# i)
251     | i >=# 10# && i <=# 15# =  unsafeChr (ord 'a' `minusInt` ten `plusInt` I# i)
252     | otherwise           =  error ("Char.intToDigit: not a digit " ++ show (I# i))
253
254 ten = I# 10#
255
256 showSignedInt :: Int -> Int -> ShowS
257 showSignedInt (I# p) (I# n) r
258     | n <# 0# && p ># 6# = '(' : itos n (')' : r)
259     | otherwise          = itos n r
260
261 itos :: Int# -> String -> String
262 itos n# cs
263     | n# <# 0# = let
264         n'# = negateInt# n#
265         in if n'# <# 0# -- minInt?
266             then '-' : itos' (negateInt# (n'# `quotInt#` 10#))
267                              (itos' (negateInt# (n'# `remInt#` 10#)) cs)
268             else '-' : itos' n'# cs
269     | otherwise = itos' n# cs
270     where
271     itos' :: Int# -> String -> String
272     itos' n# cs
273         | n# <# 10#  = C# (chr# (ord# '0'# +# n#)) : cs
274         | otherwise = case chr# (ord# '0'# +# (n# `remInt#` 10#)) of { c# ->
275                       itos' (n# `quotInt#` 10#) (C# c# : cs) }
276 \end{code}