{-# LANGUAGE TypeSynonymInstances #-} -- --------------------------------------------------------------------------- -- | -- Module : Text.Show.ByteString -- Copyright : (c) 2008 Dan Doel -- Maintainer : Dan Doel -- Stability : Experimental -- Portability : Non-portable (type synonym instances) -- -- Efficiently convert from values to lazy byte strings. module Text.Show.ByteString ( -- * The Show class Show (..) , show -- * Putting Chars , putAscii , putUTF8 -- * Putting Strings , putAsciiStr , putUTF8Str -- * Putting digits , unsafePutDigit , putDigit -- * Putting integers , showpIntAtBase -- * Putting floats , showpGFloat , showpFFloat , showpEFloat -- * Combining builders , unlinesP , unwordsP , showpParen -- * Printing values , print -- * Put , Put , PutM(..) , runPut ) where import Prelude hiding (Show(..), print, putStrLn) import qualified Prelude import Data.Binary.Put import Data.ByteString.Lazy import Data.Int import Data.Word import Data.Ratio import Data.Complex import Data.Array import qualified Data.Map as M import qualified Data.Set as S import Text.Show.ByteString.Util ( putAscii , putUTF8 , putAsciiStr, putUTF8Str , unsafePutDigit ) import Text.Show.ByteString.Char import Text.Show.ByteString.Int import Text.Show.ByteString.Integer import Text.Show.ByteString.Float -- | Conversion of values to readable byte strings. -- Minimal complete definition: 'showp' or 'showpPrec' class Show a where -- | Encodes a value to an efficient byte string builder. -- The precedence is used to determine where to put -- parentheses in a shown expression involving operators. -- -- Values of type Put can be efficiently combined, so the -- showp functions are available for showing multiple values -- before producing an output byte string. showpPrec :: Int -> a -> Put -- | Encodes a value to an efficient byte string builder. -- Values of type Put can be efficiently combined, so this -- is available for building strings from multiple values. showp :: a -> Put -- | Allows for specialized display of lists of values. -- This is used, for example, when showing arrays of Chars. showpList :: [a] -> Put showpPrec _ = showp showp = showpPrec 0 showpList [] = putWord8 91 >> putWord8 93 -- "[]" showpList (x:xs) = putWord8 91 >> showp x >> go xs -- "[.. where go (y:ys) = putWord8 44 >> showp y >> go ys -- ..,.. go [ ] = putWord8 93 -- ..]" -- | Encode a single value into a byte string show :: Show a => a -> ByteString show = runPut . showp -- | A utility function for surrounding output by parentheses -- conditionally. showpParen :: Bool -> Put -> Put showpParen b p | b = putAscii '(' >> p >> putAscii ')' | otherwise = p -- | Print a value to the standard output print :: Show a => a -> IO () print = putStrLn . show -- | Merge several string builders, separating them by newlines unlinesP :: [Put] -> Put unlinesP [ ] = return () unlinesP (p:ps) = p >> putAscii '\n' >> unlinesP ps -- | Merge several string builders, separating them by spaces unwordsP :: [Put] -> Put unwordsP [ ] = return () unwordsP [p] = p unwordsP (p:ps) = p >> putAscii ' ' >> unwordsP ps -- | Puts the digit corresponding to the Int passed in. putDigit :: Int -> Put putDigit i | i < 0 = error $ "putDigit: Negative integer: " ++ Prelude.show i | i > 9 = error $ "putDigit: Non-decimal digit: " ++ Prelude.show i | otherwise = unsafePutDigit i -- This may be a bad idea, but I'm trying it out instance Show Put where showp p = p instance Show () where showp () = putAscii '(' >> putAscii ')' instance Show Char where showp = showpChar showpList = showpString instance Show Bool where showp True = putAsciiStr "True" showp False = putAsciiStr "False" instance (Show a) => Show [a] where showp = showpList instance Show Int where showp = showpInt showpPrec k i = showpParen (i < 0 && k > 0) $ showpInt i instance Show Int8 where showp = showpInt8 showpPrec k i = showpParen (i < 0 && k > 0) $ showpInt8 i instance Show Int16 where showp = showpInt16 showpPrec k i = showpParen (i < 0 && k > 0) $ showpInt16 i instance Show Int32 where showp = showpInt32 showpPrec k i = showpParen (i < 0 && k > 0) $ showpInt32 i instance Show Int64 where showp = showpInt64 showpPrec k i = showpParen (i < 0 && k > 0) $ showpInt64 i instance Show Word where showp = showpWord instance Show Word8 where showp = showpWord8 instance Show Word16 where showp = showpWord16 instance Show Word32 where showp = showpWord32 instance Show Word64 where showp = showpWord64 instance Show Integer where showp = showpInteger showpPrec k i = showpParen (i < 0 && k > 0) $ showpInteger i instance Show Float where showp = showpGFloat Nothing showpPrec k f = showpParen (f < 0 && k > 0) $ showpGFloat Nothing f instance Show Double where showp = showpGFloat Nothing showpPrec k f = showpParen (f < 0 && k > 0) $ showpGFloat Nothing f instance (Show a, Integral a) => Show (Ratio a) where showpPrec k q = showpParen (k > 7) $ showpPrec 8 (numerator q) >> putAscii '%' >> showp (denominator q) instance (Show a, RealFloat a) => Show (Complex a) where showpPrec k (a :+ b) = showpParen (k > 6) $ showpPrec 7 a >> putAscii ' ' >> putAscii ':' >> putAscii '+' >> putAscii ' ' >> showpPrec 7 b instance Show a => Show (Maybe a) where showpPrec _ Nothing = putAsciiStr "Nothing" showpPrec k (Just a) = showpParen (k > 10) $ putAsciiStr "Just " >> showpPrec 11 a instance (Show a, Show b) => Show (Either a b) where showpPrec k (Left a) = showpParen (k > 10) $ putAsciiStr "Left " >> showpPrec 11 a showpPrec k (Right b) = showpParen (k > 10) $ putAsciiStr "Right " >> showpPrec 11 b instance Show Ordering where showp LT = putAscii 'L' >> putAscii 'T' showp EQ = putAscii 'E' >> putAscii 'Q' showp GT = putAscii 'G' >> putAscii 'T' instance (Show a, Show b) => Show (a,b) where showp (a,b) = putAscii '(' >> showp a >> putAscii ',' >> showp b >> putAscii ')' instance (Show a, Show b, Show c) => Show (a,b,c) where showp (a,b,c) = putAscii '(' >> showp a >> putAscii ',' >> showp b >> putAscii ',' >> showp c >> putAscii ')' instance (Show a, Show b, Show c, Show d) => Show (a,b,c,d) where showp (a,b,c,d) = putAscii '(' >> showp a >> putAscii ',' >> showp b >> putAscii ',' >> showp c >> putAscii ',' >> showp d >> putAscii ')' instance (Show a, Show b, Show c, Show d, Show e) => Show (a,b,c,d,e) where showp (a,b,c,d,e) = putAscii '(' >> showp a >> putAscii ',' >> showp b >> putAscii ',' >> showp c >> putAscii ',' >> showp d >> putAscii ',' >> showp e >> putAscii ')' instance (Show a, Show b, Show c, Show d, Show e, Show f) => Show (a,b,c,d,e,f) where showp (a,b,c,d,e,f) = putAscii '(' >> showp a >> putAscii ',' >> showp b >> putAscii ',' >> showp c >> putAscii ',' >> showp d >> putAscii ',' >> showp e >> putAscii ',' >> showp f >> putAscii ')' instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g) => Show (a,b,c,d,e,f,g) where showp (a,b,c,d,e,f,g) = putAscii '(' >> showp a >> putAscii ',' >> showp b >> putAscii ',' >> showp c >> putAscii ',' >> showp d >> putAscii ',' >> showp e >> putAscii ',' >> showp f >> putAscii ',' >> showp g >> putAscii ')' instance (Show i, Show e, Ix i) => Show (Array i e) where showpPrec k a = showpParen (k > 10) $ putAsciiStr "array " >> showp (bounds a) >> putAscii ' ' >> showp (assocs a) instance (Show k, Show v) => Show (M.Map k v) where showpPrec k m = showpParen (k > 10) $ putAsciiStr "fromList " >> showp (M.toList m) instance (Show e) => Show (S.Set e) where showpPrec k s = showpParen (k > 10) $ putAsciiStr "fromList " >> showp (S.toList s)