pragmatic-show 0.1.1.0 → 0.1.2.0
raw patch · 3 files changed
+160/−18 lines, 3 filesdep +containersPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: containers
API changes (from Hackage documentation)
- Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show Data.Char.GeneralCategory
- Text.Show.Pragmatic: shows :: Show a => a -> ShowS
+ Text.Show.Pragmatic: class Show a => ShowMagnitudeRangeLimited a
+ Text.Show.Pragmatic: instance (GHC.Float.RealFloat a, Text.Show.Pragmatic.Show (Data.Complex.Complex a), Text.Show.Pragmatic.ShowMagnitudeRangeLimited a) => Text.Show.Pragmatic.ShowMagnitudeRangeLimited (Data.Complex.Complex a)
+ Text.Show.Pragmatic: instance (Text.Show.Pragmatic.Show a, GHC.Classes.Ord a) => Text.Show.Pragmatic.Show (Data.Sequence.Internal.Seq a)
+ Text.Show.Pragmatic: instance (Text.Show.Pragmatic.Show a, GHC.Classes.Ord a) => Text.Show.Pragmatic.Show (Data.Set.Internal.Set a)
+ Text.Show.Pragmatic: instance (Text.Show.Pragmatic.Show a, GHC.Classes.Ord a, Text.Show.Pragmatic.Show b) => Text.Show.Pragmatic.Show (Data.Map.Internal.Map a b)
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show (Data.Complex.Complex GHC.Types.Double)
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show (Data.Complex.Complex GHC.Types.Float)
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show Control.Exception.Base.TypeError
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show Data.IntSet.Internal.IntSet
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show Data.Typeable.Internal.SomeTypeRep
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show Foreign.C.Types.CBool
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Generics.Associativity
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Generics.DecidedStrictness
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Generics.Fixity
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Generics.SourceStrictness
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Generics.SourceUnpackedness
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.IO.Exception.CompactionFailed
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.IO.Handle.Lock.FileLockingNotSupported
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.CCFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.ConcFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.DebugFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.DoCostCentres
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.DoHeapProfile
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.DoTrace
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.GCFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.GiveGCStats
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.MiscFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.ParFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.ProfFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.RTSFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.TickyFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.RTS.Flags.TraceFlags
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Stack.Types.CallStack
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Stack.Types.SrcLoc
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.StaticPtr.StaticPtrInfo
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Stats.RTSStats
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.TypeLits.SomeSymbol
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.TypeNats.SomeNat
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Types.Module
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Types.TyCon
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show GHC.Unicode.GeneralCategory
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CBlkCnt
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CBlkSize
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CClockId
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CFsBlkCnt
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CFsFilCnt
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CId
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CKey
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show System.Posix.Types.CTimer
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show a => Text.Show.Pragmatic.Show (Data.Tree.Tree a)
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.Show b => Text.Show.Pragmatic.Show (Data.IntMap.Internal.IntMap b)
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.ShowMagnitudeRangeLimited Foreign.C.Types.CDouble
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.ShowMagnitudeRangeLimited Foreign.C.Types.CFloat
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.ShowMagnitudeRangeLimited GHC.Types.Double
+ Text.Show.Pragmatic: instance Text.Show.Pragmatic.ShowMagnitudeRangeLimited GHC.Types.Float
+ Text.Show.Pragmatic: showsPrecMagnitudeRangeLimited :: ShowMagnitudeRangeLimited a => Int -> Int -> a -> ShowS
+ Text.Show.Pragmatic: showsPrecWithSharedPrecision :: (ShowMagnitudeRangeLimited n, RealFloat sn, Traversable list) => (n -> sn) -> Int -> Int -> list n -> list ShowS
- Text.Show.Pragmatic: class Show a where showsPrec _ x = (show x ++) show = (`shows` "") showList [] = ("[]" ++) showList (x : xs) = ('[' :) . shows x . flip (foldr (\ y -> (',' :) . shows y)) xs . (']' :)
+ Text.Show.Pragmatic: class Show a
Files
- Text/Show/Pragmatic.hs +138/−8
- pragmatic-show.cabal +2/−1
- test/tasty/test.hs +20/−9
Text/Show/Pragmatic.hs view
@@ -8,16 +8,30 @@ -- Portability : portable -- -{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-} -module Text.Show.Pragmatic where+module Text.Show.Pragmatic (+ -- * Replacement for the standard class+ Show(..), print+ -- * Utility (unstable)+ , ltdPrecShowsPrec+ , showsPrecWithSharedPrecision+ , ShowMagnitudeRangeLimited(..)+ ) where -import Prelude hiding (Show(..), shows)+import Prelude hiding (Show(..), shows, print) import qualified Prelude+import Data.Foldable (toList)+import Data.List (intersperse, minimumBy)+import Data.Ord (comparing) import Data.Int (Int8, Int16, Int32, Int64) import Data.Word (Word8, Word16, Word32, Word64) import Data.Ratio+import Data.Complex (Complex((:+)), magnitude) #if MIN_VERSION_base(4,8,0) import Numeric.Natural (Natural) #endif@@ -133,8 +147,15 @@ import Data.Void #endif +import qualified Data.Set as Set+import qualified Data.IntSet as ℤSet+import qualified Data.Map as Map+import qualified Data.IntMap as ℤMap+import qualified Data.Sequence as Seq+import qualified Data.Tree as Tree + -- | A drop-in replacement for 'Prelude.Show'. The behaviour is mostly the same: -- the result of 'show' should be valid Haskell code, and 'read'ing back such a -- value should give the original value – but, unlike in 'Prelude.Show', we don't@@ -155,9 +176,12 @@ show :: a -> String show = (`shows`"") showList :: [a] -> ShowS- showList [] = ("[]"++)- showList (x:xs) = ('[':) . shows x . flip (foldr (\y -> (',':) . shows y)) xs . (']':)+ showList = defaultShowList +defaultShowList :: Show a => [a] -> ShowS+defaultShowList [] = ("[]"++)+defaultShowList (x:xs) = ('[':) . shows x . flip (foldr (\y -> (',':) . shows y)) xs . (']':)+ shows :: Show a => a -> ShowS shows = showsPrec 0 @@ -450,27 +474,99 @@ (r,"'") -> (r++) +class Show a => ShowMagnitudeRangeLimited a where+ showsPrecMagnitudeRangeLimited :: Int -> Int -> a -> ShowS+ instance Show Float where showsPrec = ltdPrecShowsPrec 7+ showList = ltdPrecShowList id 7+instance ShowMagnitudeRangeLimited Float where+ showsPrecMagnitudeRangeLimited = ltdPrecShowsPrec instance Show Double where showsPrec = ltdPrecShowsPrec 10+ showList = ltdPrecShowList id 10+instance ShowMagnitudeRangeLimited Double where+ showsPrecMagnitudeRangeLimited = ltdPrecShowsPrec instance Show CFloat where showsPrec = ltdPrecShowsPrec 5+ showList = ltdPrecShowList id 5+instance ShowMagnitudeRangeLimited CFloat where+ showsPrecMagnitudeRangeLimited = ltdPrecShowsPrec instance Show CDouble where showsPrec = ltdPrecShowsPrec 10+ showList = ltdPrecShowList id 10+instance ShowMagnitudeRangeLimited CDouble where+ showsPrecMagnitudeRangeLimited = ltdPrecShowsPrec +ltdPrecShowList :: (ShowMagnitudeRangeLimited n, RealFloat sn)+ => (n -> sn) -> Int -> [n] -> ShowS+ltdPrecShowList realise precision vals+ = ('[':) . flip (foldr id)+ (intersperse (',':)+ $ showsPrecWithSharedPrecision realise precision 0 vals)+ . (']':)++showsPrecWithSharedPrecision :: (ShowMagnitudeRangeLimited n, RealFloat sn, Traversable list)+ => (n -> sn) -- ^ Magnitude-function. Should be a norm.+ -> Int -- ^ Precision of the type, in significant decimals. This will+ -- be used to trim the length of all entries to match the+ -- expected numerical uncertainty of the biggest one.+ -> Int -- ^ Precedence of the enclosing context in which the values+ -- are to be shown.+ -> list n -- ^ Values to show+ -> list ShowS -- ^ Individual values' string representation.+showsPrecWithSharedPrecision realise precision p vals+ = fmap (\val ->+ let uMagn = usableMagnitude $ realise val+ in showsPrecMagnitudeRangeLimited+ (max 0 $ precision - floor (maxUMag - uMagn)) p val+ ) vals+ where usableMagnitude n+ | n<0 = usableMagnitude (-n)+ | n==n, 2*n>n = logBase 10 n+ | otherwise = -1/0+ maxUMag = maximum $ usableMagnitude . realise <$> vals+ -- | @'ltdPrecShowsPrec' prcn@ displays floating-point values with a precision -- of at least @prcn@ digits. That does not mean it will necessarily display -- that many digits, rather it tries to always choose the shortest representation -- with the required precision. ltdPrecShowsPrec :: (RealFloat n) => Int -> Int -> n -> ShowS-ltdPrecShowsPrec _ _ 0 = ("0"++)-ltdPrecShowsPrec precision p n+ltdPrecShowsPrec precision p n cont+ = minimumBy (comparing length)+ [ postProc $ ltdPrecShowsPrecDecimal precision p' (preProc n) ""+ | (preProc, p', postProc)+ <- [ (id, p, id) ]+ ++[ ( (/μ)+ , 7, \s -> case s of+ "1" -> sμ ""+ "(-1)"-> showParen (p>=6) (('-':) . sμ) ""+ _ -> showParen (p>7) ((s++) . ('*':) . sμ) ""+ )+ | (μ,sμ) <- (pi, ("pi"++))+ :[ (pi / fromIntegral m, ("pi/"++) . shows m)+ | m<-[2,3,4 :: Int] ]+ ++[ (sqrt $ fromIntegral n, ("sqrt "++) . shows n)+ | n<-[2,3,5 :: Int] ]+ ++[ ( sqrt (fromIntegral n)/fromIntegral m+ , ("sqrt "++) . shows n . ('/':) . shows m)+ | n<-[2,3 :: Int]+ , m<-[2,3 :: Int] ]+ ]+ ++[ ( (*fromIntegral n)+ , 7, \s -> showParen (p>7) ((s++) . ('/':) . shows n) "" )+ | n<-[3,7,9 :: Int] ]+ ] ++ cont++ltdPrecShowsPrecDecimal :: (RealFloat n) => Int -> Int -> n -> ShowS+ltdPrecShowsPrecDecimal _ _ 0 = ("0"++)+ltdPrecShowsPrecDecimal precision p n | not (n==n) = ("NaN"++)- | n<0 = showParen (p>5) $ ('-':) . ltdPrecShowsPrec precision 0 (negate n)+ | n<0 = showParen (p>5)+ $ ('-':) . ltdPrecShowsPrecDecimal precision 0 (negate n) | n==n*2 = ("Infinity"++) | e₁₀<7 && lrDigs <= e₁₀ = (rDigits++) . (replicate (e₁₀-lrDigs) '0' ++)@@ -494,6 +590,20 @@ instance (Show a) => Show [a] where showsPrec _ = showList +instance (Show a, Ord a) => Show (Seq.Seq a) where+ showsPrec _ = defaultShowList . toList+instance (Show a, Ord a) => Show (Set.Set a) where+ showsPrec _ = defaultShowList . Set.toList+instance Show ℤSet.IntSet where+ showsPrec _ = defaultShowList . ℤSet.toList+instance (Show a, Ord a, Show b) => Show (Map.Map a b) where+ showsPrec _ = defaultShowList . Map.toList+instance (Show b) => Show (ℤMap.IntMap b) where+ showsPrec _ = defaultShowList . ℤMap.toList+instance (Show a) => Show (Tree.Tree a) where+ showsPrec p (Tree.Node a st) = showParen (p>9)+ $ ("Node "++) . showsPrec 11 a . (' ':) . shows st+ instance (Show a, Show b) => Show (a,b) where showsPrec _ (a,b) = ('(':) . shows a . (',':) . shows b . (')':) instance (Show a, Show b, Show c) => Show (a,b,c) where@@ -509,6 +619,26 @@ | denominator n == 1 = shows $ numerator n | otherwise = showParen (p>6) $ shows (numerator n) . ('/':) . shows (denominator n)++instance Show (Complex Double) where+ showsPrec = ltdPrecShowsPrecComplex 10+ showList = ltdPrecShowList magnitude 10+instance Show (Complex Float) where+ showsPrec = ltdPrecShowsPrecComplex 7+ showList = ltdPrecShowList magnitude 7+instance (RealFloat a, Show (Complex a), ShowMagnitudeRangeLimited a)+ => ShowMagnitudeRangeLimited (Complex a) where+ showsPrecMagnitudeRangeLimited = ltdPrecShowsPrecComplex++ltdPrecShowsPrecComplex :: (RealFloat r, ShowMagnitudeRangeLimited r)+ => Int -> Int -> Complex r -> ShowS+ltdPrecShowsPrecComplex precision p (r:+i)+ | abs r > abs i * 10^precision+ = ltdPrecShowsPrec precision p r+ | otherwise+ = case ($"")<$>showsPrecWithSharedPrecision id precision 6 [r,i] of+ [sr,"0"] -> showParen (p>7) $ (sr++)+ [sr,si] -> showParen (p>6) $ (sr++) . (":+"++) . (si++) -- | Drop-in for the standard screen-displaying function. This is useful as a GHCi -- evaluation action; invoke with
pragmatic-show.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: pragmatic-show-version: 0.1.1.0+version: 0.1.2.0 synopsis: Alternative Show class that gives shorter view if possible. description: The standard 'Show' class is handy for quickly viewing any Haskell values without having to think about formatting. However, it often@@ -25,6 +25,7 @@ -- other-modules: other-extensions: FlexibleInstances build-depends: base >=4.8 && <5+ , containers >=0.5 && <0.6 -- hs-source-dirs: default-language: Haskell2010
test/tasty/test.hs view
@@ -20,6 +20,7 @@ import Prelude hiding (Show(..)) import Text.Show.Pragmatic +import Data.Complex (Complex((:+))) import Data.VectorSpace @@ -43,9 +44,10 @@ [ floatTest 1 "1" , floatTest 10 "10" , floatTest 0.1 "0.1"+ , floatTest (1/3) "1/3" , floatTest 1e9 "1e9" , floatTest 1e90 "1e90"- , floatTest pi "3.14159265359"+ , floatTest pi "pi" , floatTest 32 "32" , floatTest (89.524 - 9.004) "80.52" , floatTest (0.3 + 0.3 + 0.3) "0.9"@@ -62,14 +64,10 @@ , floatTest 7e35 "7e35" , floatTest (1/0) "Infinity" , floatTest (sqrt $ -1) "NaN"- ]- , testGroup "Re-Reading of approximate types"- [ testProperty "Double" $ readBackApproxEq ([]::[Double]) 1e-10- , testProperty "Double with higher-than-supported precision"- . QC.expectFailure- $ readBackApproxEq ([]::[Double]) 1e-14- , testProperty "Double²" $ readBackApproxEq ([]::[(Double,Double)]) 1e-10- , testProperty "Float" $ readBackApproxEq ([]::[Float]) 1e-5+ , floatsTest [1,2,3] "[1,2,3]"+ , floatsTest (take 10 $ iterate (/16) 1)+ "[1,0.0625,3.90625e-3,2.44140625e-4,1.5258789e-5,9.53674e-7,5.9605e-8,3.725e-9,2.33e-10,1.5e-11]"+ , floatsTest [1, -sqrt 2, sqrt (-2)] "[1,-sqrt 2,NaN]" ] , testGroup "Showing rational numbers" [ rationalTest 0 "0"@@ -79,6 +77,13 @@ , rationalTest (-268/19) "-268/19" , rationalTest (3/3) "1" ]+ , testGroup "Showing complex numbers"+ [ complexTest 1 "1"+ , complexTest (sqrt $ -1) "0:+1"+ , complexTest (exp $ 0:+pi) "-1"+ , complexTest (exp $ 0:+pi/4) "sqrt 2/2:+sqrt 2/2"+ , complexTest (exp $ 0:+5*pi/4) "(-sqrt 2/2):+(-sqrt 2/2)"+ ] ] -- | Check that showing and reading again yields the original value.@@ -99,6 +104,12 @@ floatTest :: Double -> String -> TestTree floatTest n s = testCase s $ show n @?= s++complexTest :: Complex Double -> String -> TestTree+complexTest n s = testCase s $ show n @?= s++floatsTest :: [Double] -> String -> TestTree+floatsTest n s = testCase s $ show n @?= s rationalTest :: Rational -> String -> TestTree rationalTest n s = testCase s $ show n @?= s