on master help sign in
Merge pull request #70 from haskell-service/instances

Derive `Show` and `Eq` instances

commit461f014142cdc9cec4bb51ceb35f38bf61503f97 authorMichael Xavier <michael@michaelxavier.net> dateFri 29 Sep 2017, 09:30 (9 years ago) parentbc424a47282343
3 files changed+82−24
katip/src/Katip/Core.hs+51−19 katip/src/Katip/Scribes/Handle.hs+1 katip/test/Katip/Tests.hs+30−5
katip/src/Katip/Core.hs+51−19
@@ -180,7 +180,7 @@ instance FromJSON Severity where
180180-------------------------------------------------------------------------------
181181-- | Log message with Builder underneath; use '<>' to concat in O(1).
182182newtype LogStr = LogStr { unLogStr :: B.Builder }
183− deriving (Generic, Show)
183+ deriving (Generic, Show, Eq)
184184
185185instance IsString LogStr where
186186 fromString = LogStr . B.fromString
@@ -247,31 +247,62 @@ data Item a = Item {
247247 } deriving (Generic, Functor)
248248makeLenses ''Item
249249
250+-- Manual instance because 'Loc' has no 'Eq' and 'Show' instances in old
251+-- versions of template-haskell (< 2.10)
252+instance Eq a => Eq (Item a) where
253+ a == b = FT.and [ _itemApp a == _itemApp b
254+ , _itemEnv a == _itemEnv b
255+ , _itemSeverity a == _itemSeverity b
256+ , _itemThread a == _itemThread b
257+ , _itemHost a == _itemHost b
258+ , _itemProcess a == _itemProcess b
259+ , _itemPayload a == _itemPayload b
260+ , _itemMessage a == _itemMessage b
261+ , _itemTime a == _itemTime b
262+ , _itemNamespace a == _itemNamespace b
263+ , case (_itemLoc a, _itemLoc b) of
264+ (Nothing, Nothing) -> True
265+ (Just l1, Just l2) -> FT.and [ loc_filename l1 == loc_filename l2
266+ , loc_package l1 == loc_package l2
267+ , loc_module l1 == loc_module l2
268+ , loc_start l1 == loc_start l2
269+ , loc_end l1 == loc_end l2
270+ ]
271+ _ -> False
272+ ]
250273
251274instance Show a => Show (Item a) where
252− show Item{..} = "Item {_itemApp = " ++ show _itemApp ++ ", " ++
253− "_itemEnv = " ++ show _itemEnv ++ ", " ++
254− "_itemSeverity = " ++ show _itemSeverity ++ ", " ++
255− "_itemThread = " ++ show _itemThread ++ ", " ++
256− "_itemHost = " ++ show _itemHost ++ ", " ++
257− "_itemProcess = " ++ show _itemProcess ++ ", " ++
258− "_itemPayload = " ++ show _itemPayload ++ ", " ++
259− "_itemMessage = " ++ show _itemMessage ++ ", " ++
260− "_itemTime = " ++ show _itemTime ++ ", " ++
261− "_itemNamespace = " ++ show _itemNamespace ++ ", " ++
262− "_itemLoc = " ++ show (LocShow <$> _itemLoc) ++ "}"
263−
275+ showsPrec d Item{..} = showParen (d >= 11) ( showString "Item {"
276+ . field "_itemApp" _itemApp
277+ . field "_itemEnv" _itemEnv
278+ . field "_itemSeverity" _itemSeverity
279+ . field "_itemThread" _itemThread
280+ . field "_itemHost" _itemHost
281+ . field "_itemProcess" _itemProcess
282+ . field "_itemPayload" _itemPayload
283+ . field "_itemMessage" _itemMessage
284+ . field "_itemTime" _itemTime
285+ . field "_itemNamespace" _itemNamespace
286+ . showString "_itemLoc = " . shows (LocShow <$> _itemLoc)
287+ . showChar '}'
288+ )
289+ where
290+ field n v = showString n . showString " = " . shows v . showString ", "
264291
265292newtype LocShow = LocShow Loc
266293
267294
268295instance Show LocShow where
269− show (LocShow Loc{..}) =
270− "Loc {loc_filename = " ++ show loc_filename ++ ", " ++
271− "loc_package = " ++ show loc_package ++ ", " ++
272− "loc_module = " ++ show loc_module ++ ", " ++
273− "loc_start = " ++ show loc_start ++ ", " ++
274− "loc_end = " ++ show loc_end ++ "}"
296+ showsPrec d (LocShow Loc{..}) = showParen (d >= 11) ( showString "Loc {"
297+ . field "loc_filename" loc_filename
298+ . field "loc_package" loc_package
299+ . field "loc_module" loc_module
300+ . field "loc_start" loc_start
301+ . showString "loc_end = " . shows loc_end
302+ . showChar '}'
303+ )
304+ where
305+ field n v = showString n . showString " = " . shows v . showString ", "
275306
276307
277308instance ToJSON a => ToJSON (Item a) where
@@ -629,6 +660,7 @@ spawnScribeWorker (Scribe write _) queue = Async.async go
629660data ScribeSettings = ScribeSettings {
630661 _scribeBufferSize :: Int
631662 }
663+ deriving (Show, Eq)
632664
633665makeLenses ''ScribeSettings
634666
katip/src/Katip/Scribes/Handle.hs+1
@@ -50,6 +50,7 @@ data ColorStrategy
5050 -- ^ Whether to use color control chars in log output
5151 | ColorIfTerminal
5252 -- ^ Color if output is a terminal
53+ deriving (Show, Eq)
5354
5455-------------------------------------------------------------------------------
5556-- | Logs to a file handle such as stdout, stderr, or a file. Contexts
katip/test/Katip/Tests.hs+30−5
@@ -25,6 +25,7 @@ import qualified Data.Text.Lazy.Builder as B
2525import Data.Time
2626import Data.Time.Clock.POSIX
2727import Language.Haskell.TH
28+import Lens.Micro (ASetter, (&), (.~))
2829import System.Posix.Types
2930import Test.QuickCheck.Instances ()
3031import Test.Tasty
@@ -41,6 +42,7 @@ tests = testGroup "Katip"
4142 [
4243 testProperty "JSON cycle Item" $ \(i :: Item ()) ->
4344 prop_json_cycle i
45+ , eqItemTests
4446 , testProperty "renderSeverity/textToSeverity cycle" $ \sev ->
4547 textToSeverity(renderSeverity sev) === Just sev
4648 , testProperty "processIDToText/textToProcessID cycle" $ \pid ->
@@ -245,11 +247,6 @@ deriving instance Arbitrary Namespace
245247deriving instance Arbitrary Environment
246248deriving instance Arbitrary ThreadIdText
247249deriving instance Arbitrary CPid
248−#if !MIN_VERSION_base(4, 8, 0)
249−deriving instance Eq Loc
250−#endif
251−deriving instance Eq LogStr
252−deriving instance (Eq a) => Eq (Item a)
253250
254251
255252-------------------------------------------------------------------------------
@@ -278,3 +275,31 @@ instance Arbitrary Severity where
278275-------------------------------------------------------------------------------
279276instance Arbitrary LogStr where
280277 arbitrary = LogStr . B.fromText <$> arbitrary
278+
279+-------------------------------------------------------------------------------
280+-- Somewhat test whether all fields are taken into account in `==`
281+
282+#if !MIN_VERSION_template_haskell(2, 10, 0)
283+-- `testProperty` requires these instances
284+deriving instance Eq Loc
285+deriving instance Show Loc
286+#endif
287+
288+eqItemTests :: TestTree
289+eqItemTests = testGroup "Eq Item"
290+ [ testProperty "itemApp" $ prop_field itemApp
291+ , testProperty "itemEnv" $ prop_field itemEnv
292+ , testProperty "itemSeverity" $ prop_field itemSeverity
293+ , testProperty "itemThread" $ prop_field itemThread
294+ , testProperty "itemHost" $ prop_field itemHost
295+ , testProperty "itemProcess" $ prop_field itemProcess
296+ , testProperty "itemPayload" $ prop_field itemPayload
297+ , testProperty "itemMessage" $ prop_field itemMessage
298+ , testProperty "itemTime" $ prop_field itemTime
299+ , testProperty "itemNamespace" $ prop_field itemNamespace
300+ , testProperty "itemLoc" $ prop_field itemLoc
301+ ]
302+ where
303+ prop_field :: Eq a => ASetter (Item ()) (Item ()) a a -> Item () -> a -> a -> Bool
304+ prop_field field item f1 f2 =
305+ ((item & field .~ f1) == (item & field .~ f2)) == (f1 == f2)