debug-print (empty) → 0.0.0.0
raw patch · 11 files changed
+412/−0 lines, 11 filesdep +aesondep +basedep +containers
Dependencies added: aeson, base, containers, debug-print, hspec, markdown-unlit, text, vector
Files
- CHANGELOG.md +5/−0
- LICENSE +21/−0
- README.lhs +48/−0
- README.md +48/−0
- debug-print.cabal +79/−0
- library/DebugPrint.hs +9/−0
- library/DebugPrint/Aeson.hs +29/−0
- library/DebugPrint/Class.hs +109/−0
- library/DebugPrint/Show.hs +16/−0
- library/DebugPrint/Tagged.hs +19/−0
- library/DebugPrint/Types.hs +29/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+## [_Unreleased_](https://github.com/freckle/debug-print/compare/v0.0.0.0...main)++## [v0.0.0.0](https://github.com/freckle/debug-print/tree/v0.0.0.0)++First tagged release.
+ LICENSE view
@@ -0,0 +1,21 @@+The MIT License (MIT)++Copyright (c) 2025 Renaissance Learning Inc++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.lhs view
@@ -0,0 +1,48 @@+# debug-print++Offers `ToDebugPrintValue`, a structured alternative to `Show`+for printing values for testing and debugging purposes.++<!--+```haskell+module Main (main) where++import Prelude++import Data.Text (Text)+import GHC.Generics (Generic)+import Text.Markdown.Unlit ()+import Test.Hspec+```+-->++```haskell+import DebugPrint+import DebugPrint.Aeson+import Data.Aeson qualified as Aeson+```++```haskell+data Report = Report+ { milliseconds :: Int+ , errors :: [Text]+ }+ deriving stock Generic+ deriving anyclass (ToDebugPrintRecord, ToDebugPrintValue)++report :: Report+report = Report{ milliseconds = 5_824+ , errors = ["Warning! Problems."] }+```++```haskell+main :: IO ()+main = hspec $ do+ it "" $ do+ Aeson.encode (debugPrintValueToAeson report) `shouldBe`+ "{\"errors\":[\"Warning! Problems.\"],\"milliseconds\":5824}"+```++---++[LICENSE](./LICENSE) | [CHANGELOG](./CHANGELOG.md)
+ README.md view
@@ -0,0 +1,48 @@+# debug-print++Offers `ToDebugPrintValue`, a structured alternative to `Show`+for printing values for testing and debugging purposes.++<!--+```haskell+module Main (main) where++import Prelude++import Data.Text (Text)+import GHC.Generics (Generic)+import Text.Markdown.Unlit ()+import Test.Hspec+```+-->++```haskell+import DebugPrint+import DebugPrint.Aeson+import Data.Aeson qualified as Aeson+```++```haskell+data Report = Report+ { milliseconds :: Int+ , errors :: [Text]+ }+ deriving stock Generic+ deriving anyclass (ToDebugPrintRecord, ToDebugPrintValue)++report :: Report+report = Report{ milliseconds = 5_824+ , errors = ["Warning! Problems."] }+```++```haskell+main :: IO ()+main = hspec $ do+ it "" $ do+ Aeson.encode (debugPrintValueToAeson report) `shouldBe`+ "{\"errors\":[\"Warning! Problems.\"],\"milliseconds\":5824}"+```++---++[LICENSE](./LICENSE) | [CHANGELOG](./CHANGELOG.md)
+ debug-print.cabal view
@@ -0,0 +1,79 @@+cabal-version: 1.18+name: debug-print+version: 0.0.0.0+license: MIT+license-file: LICENSE+maintainer: Freckle Education+homepage: https://github.com/freckle/debug-print#readme+bug-reports: https://github.com/freckle/debug-print/issues+synopsis: A structured alternative to Show+category: Debug+build-type: Simple+extra-doc-files:+ README.md+ CHANGELOG.md++source-repository head+ type: git+ location: https://github.com/freckle/debug-print++library+ exposed-modules:+ DebugPrint+ DebugPrint.Aeson+ DebugPrint.Class+ DebugPrint.Show+ DebugPrint.Tagged+ DebugPrint.Types++ hs-source-dirs: library+ other-modules: Paths_debug_print+ default-language: GHC2021+ default-extensions:+ DefaultSignatures DeriveAnyClass DerivingVia NoFieldSelectors+ NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings+ StrictData++ ghc-options:+ -Weverything -Wno-all-missed-specialisations+ -Wno-missing-import-lists -Wno-missing-kind-signatures+ -Wno-missing-safe-haskell-mode -Wno-safe -Wno-unsafe++ build-depends:+ aeson >=2.2.3.0,+ base >=4.19.2.0 && <5,+ containers >=0.6.8,+ text >=2.1.1,+ vector >=0.13.2.0++ if impl(ghc >=9.8)+ ghc-options:+ -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures++test-suite readme+ type: exitcode-stdio-1.0+ main-is: README.lhs+ other-modules: Paths_debug_print+ default-language: GHC2021+ default-extensions:+ DefaultSignatures DeriveAnyClass DerivingVia NoFieldSelectors+ NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings+ StrictData++ ghc-options:+ -Weverything -Wno-all-missed-specialisations+ -Wno-missing-import-lists -Wno-missing-kind-signatures+ -Wno-missing-safe-haskell-mode -Wno-safe -Wno-unsafe -pgmL+ markdown-unlit++ build-depends:+ aeson >=2.2.3.0,+ base >=4.19.2.0 && <5,+ debug-print,+ hspec >=2.11.11,+ markdown-unlit >=0.6.0,+ text >=2.1.1++ if impl(ghc >=9.8)+ ghc-options:+ -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures
+ library/DebugPrint.hs view
@@ -0,0 +1,9 @@+module DebugPrint+ ( DebugPrintValue (..)+ , DebugPrintRecord (..)+ , ToDebugPrintValue (..)+ , ToDebugPrintRecord (..)+ ) where++import DebugPrint.Class+import DebugPrint.Types
+ library/DebugPrint/Aeson.hs view
@@ -0,0 +1,29 @@+module DebugPrint.Aeson+ ( debugPrintRecordToAeson+ , debugPrintValueToAeson+ ) where++import Prelude++import Data.Aeson qualified as Aeson+import Data.Aeson.Key qualified as Key+import Data.Aeson.KeyMap qualified as KeyMap+import Data.Bifunctor (bimap)+import Data.Map.Strict qualified as Map+import DebugPrint.Class+import DebugPrint.Types++debugPrintRecordToAeson :: ToDebugPrintRecord a => a -> Aeson.Object+debugPrintRecordToAeson a =+ let DebugPrintRecord m = toDebugPrintRecord a+ in KeyMap.fromList+ $ bimap Key.fromText debugPrintValueToAeson+ <$> Map.toList m++debugPrintValueToAeson :: ToDebugPrintValue a => a -> Aeson.Value+debugPrintValueToAeson a = case toDebugPrintValue a of+ DebugPrintValueInt x -> Aeson.Number $ fromIntegral x+ DebugPrintValueText x -> Aeson.String x+ DebugPrintValueBool x -> Aeson.Bool x+ DebugPrintValueVector x -> Aeson.Array $ fmap debugPrintValueToAeson x+ DebugPrintValueRecord x -> Aeson.Object $ debugPrintRecordToAeson x
+ library/DebugPrint/Class.hs view
@@ -0,0 +1,109 @@+-- | Generic-derivable classes for converting to 'DebugPrintRecord' and 'Value'+--+-- These classes are designed to be used only for pretty-printing in tests+-- and logging. They should generally be used anywhere you would derive 'Show'.+module DebugPrint.Class+ ( ToDebugPrintValue (..)+ , ToDebugPrintRecord (..)+ , ToDebugPrintValueRep+ , ToDebugPrintRecordRep+ ) where++import Prelude++import Data.Foldable (toList)+import Data.Kind (Type)+import Data.List.NonEmpty (NonEmpty)+import Data.Map.Strict qualified as Map+import Data.Sequence (Seq)+import Data.Text qualified as T+import Data.Text.Lazy qualified as TL+import Data.Vector (Vector)+import Data.Vector qualified as V+import DebugPrint.Types+import GHC.Generics+import Numeric.Natural (Natural)++class ToDebugPrintValue a where+ toDebugPrintValue :: a -> DebugPrintValue+ default toDebugPrintValue+ :: (Generic a, ToDebugPrintRecordRep (Rep a)) => a -> DebugPrintValue+ toDebugPrintValue = DebugPrintValueRecord . gToRecord . from++instance ToDebugPrintValue DebugPrintValue where+ toDebugPrintValue = id++instance ToDebugPrintValue Int where+ toDebugPrintValue = DebugPrintValueInt++instance ToDebugPrintValue Char where+ toDebugPrintValue = DebugPrintValueText . T.singleton++instance ToDebugPrintValue Natural where+ toDebugPrintValue = DebugPrintValueInt . fromIntegral++instance ToDebugPrintValue T.Text where+ toDebugPrintValue = DebugPrintValueText++instance ToDebugPrintValue TL.Text where+ toDebugPrintValue = DebugPrintValueText . TL.toStrict++instance ToDebugPrintValue Bool where+ toDebugPrintValue = DebugPrintValueBool++instance ToDebugPrintValue a => ToDebugPrintValue (Maybe a) where+ toDebugPrintValue = toDebugPrintValue . toList++instance ToDebugPrintValue a => ToDebugPrintValue [a] where+ toDebugPrintValue = toDebugPrintValue . V.fromList++instance ToDebugPrintValue a => ToDebugPrintValue (NonEmpty a) where+ toDebugPrintValue = toDebugPrintValue . toList++instance ToDebugPrintValue a => ToDebugPrintValue (Seq a) where+ toDebugPrintValue = toDebugPrintValue . toList++instance ToDebugPrintValue a => ToDebugPrintValue (Vector a) where+ toDebugPrintValue = DebugPrintValueVector . fmap toDebugPrintValue++---++class ToDebugPrintRecord a where+ toDebugPrintRecord :: a -> DebugPrintRecord+ default toDebugPrintRecord+ :: (Generic a, ToDebugPrintRecordRep (Rep a)) => a -> DebugPrintRecord+ toDebugPrintRecord = gToRecord . from++instance ToDebugPrintRecord DebugPrintRecord where+ toDebugPrintRecord = id++---++class ToDebugPrintValueRep (f :: Type -> Type) where+ gToValue :: f a -> DebugPrintValue++instance ToDebugPrintValue a => ToDebugPrintValueRep (K1 i a) where+ gToValue (K1 x) = toDebugPrintValue x++---++class ToDebugPrintRecordRep (f :: Type -> Type) where+ gToRecord :: f a -> DebugPrintRecord++instance ToDebugPrintRecordRep U1 where+ gToRecord _ = DebugPrintRecord mempty++instance+ (ToDebugPrintRecordRep f, ToDebugPrintRecordRep g)+ => ToDebugPrintRecordRep (f :*: g)+ where+ gToRecord (x :*: y) = gToRecord x <> gToRecord y++instance ToDebugPrintRecordRep f => ToDebugPrintRecordRep (D1 i f) where+ gToRecord (M1 x) = gToRecord x++instance ToDebugPrintRecordRep f => ToDebugPrintRecordRep (C1 i f) where+ gToRecord (M1 x) = gToRecord x++instance (Selector s, ToDebugPrintValueRep f) => ToDebugPrintRecordRep (S1 s f) where+ gToRecord s1@(M1 x) = DebugPrintRecord $ Map.singleton (T.pack (selName s1)) (gToValue x)
+ library/DebugPrint/Show.hs view
@@ -0,0 +1,16 @@+module DebugPrint.Show+ ( DebugShow (..)+ ) where++import Prelude++import Data.Text qualified as T+import DebugPrint.Class++-- | For use with deriving-via, provides a simple 'ToDebugPrintValue'+-- instance based on 'Show' which renders as text+newtype DebugShow a = DebugShow a++instance Show a => ToDebugPrintValue (DebugShow a) where+ toDebugPrintValue (DebugShow x) =+ toDebugPrintValue $ T.pack $ show x
+ library/DebugPrint/Tagged.hs view
@@ -0,0 +1,19 @@+module DebugPrint.Tagged+ ( tag+ , Tagged (..)+ ) where++import Prelude++import Data.Text qualified as T+import DebugPrint.Class+import DebugPrint.Types+import GHC.Generics (Generic)++-- | Useful for debug-printing discriminated unions+data Tagged = Tagged {tag :: T.Text, value :: DebugPrintValue}+ deriving stock (Generic)+ deriving anyclass (ToDebugPrintRecord, ToDebugPrintValue)++tag :: ToDebugPrintValue a => T.Text -> a -> DebugPrintValue+tag t = toDebugPrintValue . Tagged t . toDebugPrintValue
+ library/DebugPrint/Types.hs view
@@ -0,0 +1,29 @@+-- | A general structure to which data values may be converted+--+-- This is often useful for testing and logging to get an output that is+-- more structured and better pretty-printed than what 'show' can offer.+module DebugPrint.Types+ ( DebugPrintRecord (..)+ , DebugPrintValue (..)+ ) where++import Prelude++import Data.Map (Map)+import Data.String (IsString (..))+import Data.Text (Text)+import Data.Text qualified as T+import Data.Vector (Vector)++newtype DebugPrintRecord = DebugPrintRecord (Map Text DebugPrintValue)+ deriving newtype (Monoid, Semigroup)++data DebugPrintValue+ = DebugPrintValueInt Int+ | DebugPrintValueText Text+ | DebugPrintValueBool Bool+ | DebugPrintValueVector (Vector DebugPrintValue)+ | DebugPrintValueRecord DebugPrintRecord++instance IsString DebugPrintValue where+ fromString = DebugPrintValueText . T.pack