contra-tracer 0.2.0.0 → 0.2.1.0
raw patch · 6 files changed
+173/−5 lines, 6 filesdep +contra-tracerPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: contra-tracer
API changes (from Hackage documentation)
+ Control.Tracer: (>$<) :: Contravariant f => (a -> b) -> f b -> f a
+ Control.Tracer: contramapM :: Monad m => (a -> m b) -> Tracer m b -> Tracer m a
+ Control.Tracer: mkTracer :: Applicative m => (a -> m ()) -> Tracer m a
+ Control.Tracer: squelchUnlessM :: Monad m => (a -> m Bool) -> Tracer m a -> Tracer m a
+ Control.Tracer: traceAll :: forall (m :: Type -> Type) t b a. (Monad m, Foldable t) => (b -> t a) -> Tracer m a -> Tracer m b
+ Control.Tracer: traceMaybeM :: Monad m => (a -> m (Maybe b)) -> Tracer m b -> Tracer m a
+ Control.Tracer: traceTraversable :: forall (m :: Type -> Type) t a. (Monad m, Foldable t) => Tracer m a -> Tracer m (t a)
- Control.Tracer: Tracer :: TracerA m a () -> Tracer m a
+ Control.Tracer: Tracer :: TracerA m a () -> Tracer (m :: Type -> Type) a
- Control.Tracer: [runTracer] :: Tracer m a -> TracerA m a ()
+ Control.Tracer: [runTracer] :: Tracer (m :: Type -> Type) a -> TracerA m a ()
- Control.Tracer: arrow :: TracerA m a () -> Tracer m a
+ Control.Tracer: arrow :: forall (m :: Type -> Type) a. TracerA m a () -> Tracer m a
- Control.Tracer: contramap :: Contravariant f => (a -> b) -> f b -> f a
+ Control.Tracer: contramap :: Contravariant f => (a' -> a) -> f a -> f a'
- Control.Tracer: debugTracer :: Applicative m => Tracer m String
+ Control.Tracer: debugTracer :: forall (m :: Type -> Type). Applicative m => Tracer m String
- Control.Tracer: infixl 4 >$
+ Control.Tracer: infixl 4 >$<
- Control.Tracer: nat :: (forall x. m x -> n x) -> TracerA m a b -> TracerA n a b
+ Control.Tracer: nat :: (forall x. () => m x -> n x) -> TracerA m a b -> TracerA n a b
- Control.Tracer: natTracer :: forall m n s. (forall x. m x -> n x) -> Tracer m s -> Tracer n s
+ Control.Tracer: natTracer :: (forall x. () => m x -> n x) -> Tracer m s -> Tracer n s
- Control.Tracer: newtype Tracer m a
+ Control.Tracer: newtype Tracer (m :: Type -> Type) a
- Control.Tracer: nullTracer :: Monad m => Tracer m a
+ Control.Tracer: nullTracer :: forall (m :: Type -> Type) a. Monad m => Tracer m a
- Control.Tracer: squelch :: Applicative m => TracerA m a ()
+ Control.Tracer: squelch :: forall (m :: Type -> Type) a. Applicative m => TracerA m a ()
- Control.Tracer: squelchUnless :: Monad m => (a -> Bool) -> Tracer m a -> Tracer m a
+ Control.Tracer: squelchUnless :: forall (m :: Type -> Type) a. Monad m => (a -> Bool) -> Tracer m a -> Tracer m a
- Control.Tracer: traceMaybe :: Monad m => (a -> Maybe b) -> Tracer m b -> Tracer m a
+ Control.Tracer: traceMaybe :: forall (m :: Type -> Type) a b. Monad m => (a -> Maybe b) -> Tracer m b -> Tracer m a
- Control.Tracer: use :: Tracer m a -> TracerA m a ()
+ Control.Tracer: use :: forall (m :: Type -> Type) a. Tracer m a -> TracerA m a ()
- Control.Tracer.Arrow: [Emitting] :: Kleisli m a x -> Kleisli m x b -> TracerA m a b
+ Control.Tracer.Arrow: [Emitting] :: forall (m :: Type -> Type) a x b. Kleisli m a x -> Kleisli m x b -> TracerA m a b
- Control.Tracer.Arrow: [Squelching] :: Kleisli m a b -> TracerA m a b
+ Control.Tracer.Arrow: [Squelching] :: forall (m :: Type -> Type) a b. Kleisli m a b -> TracerA m a b
- Control.Tracer.Arrow: compute :: Applicative m => (a -> b) -> TracerA m a b
+ Control.Tracer.Arrow: compute :: forall (m :: Type -> Type) a b. Applicative m => (a -> b) -> TracerA m a b
- Control.Tracer.Arrow: data TracerA m a b
+ Control.Tracer.Arrow: data TracerA (m :: Type -> Type) a b
- Control.Tracer.Arrow: nat :: (forall x. m x -> n x) -> TracerA m a b -> TracerA n a b
+ Control.Tracer.Arrow: nat :: (forall x. () => m x -> n x) -> TracerA m a b -> TracerA n a b
- Control.Tracer.Arrow: runTracerA :: Monad m => TracerA m a () -> Kleisli m a ()
+ Control.Tracer.Arrow: runTracerA :: forall (m :: Type -> Type) a. Monad m => TracerA m a () -> Kleisli m a ()
- Control.Tracer.Arrow: squelch :: Applicative m => TracerA m a ()
+ Control.Tracer.Arrow: squelch :: forall (m :: Type -> Type) a. Applicative m => TracerA m a ()
Files
- CHANGELOG.md +7/−0
- README.md +1/−1
- contra-tracer.cabal +24/−1
- src/Control/Tracer.hs +47/−3
- src/Test/Control/Tracer/Properties.hs +56/−0
- test/Main.hs +38/−0
CHANGELOG.md view
@@ -1,3 +1,10 @@+# 0.2.1.0++- `traceAll` and `traceTraversable` defined (https://github.com/avieth/contra-tracer/pull/9)+- `mkTracer`, `contramapM`, `traceMaybeM`, and `squelchUnlessM` defined (https://github.com/avieth/contra-tracer/pull/8)+- Re-export the `(>$<)` operator (https://github.com/avieth/contra-tracer/pull/5)+- Haddock and README fixes (https://github.com/avieth/contra-tracer/pull/4) (https://github.com/avieth/contra-tracer/pull/7)+ # 0.2.0.0 - Renamed `Control.Tracer.Arrow.Tracer` to `Control.Tracer.Arrow.TracerA`
README.md view
@@ -29,7 +29,7 @@ -- Puts text to stdout. stdoutTracer :: Tracer IO Text --- A somain-specific event type.+-- A domain-specific event type. data Event = EventA | EventB Int -- The log format for an Event.
contra-tracer.cabal view
@@ -1,5 +1,5 @@ name: contra-tracer-version: 0.2.0.0+version: 0.2.1.0 synopsis: Arrow and contravariant tracers description: A simple interface for logging, tracing and monitoring license: Apache-2.0@@ -25,3 +25,26 @@ build-depends: base < 5 if impl(ghc < 8.5) build-depends: contravariant+ ghc-options: -Wall+ -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ -Wpartial-fields+ -Wredundant-constraints++test-suite contra-tracer-tests+ type: exitcode-stdio-1.0+ hs-source-dirs: test, src+ main-is: Main.hs+ other-modules:+ Test.Control.Tracer.Properties+ Control.Tracer+ Control.Tracer.Arrow+ default-language: Haskell2010++ build-depends:+ base < 5+ , contra-tracer++ if impl(ghc < 8.5)+ build-depends:+ contravariant
src/Control/Tracer.hs view
@@ -45,7 +45,7 @@ > main = do > textTacer <- traceToLogFile "log.txt" > let eventTracer :: Tracer IO Event-> eventTracer = contramap eventToText tracer+> eventTracer = contramap eventToText textTracer > actionWithTrace eventTracer -} @@ -54,6 +54,7 @@ module Control.Tracer ( Tracer (..)+ , mkTracer , traceWith , arrow , use@@ -68,14 +69,22 @@ , natTracer , Arrow.nat , traceMaybe+ , traceMaybeM+ , traceAll+ , traceTraversable , squelchUnless+ , squelchUnlessM -- * Re-export of Contravariant , Contravariant(..)+ , (>$<)+ , contramapM ) where import Control.Arrow ((|||), (&&&), arr, runKleisli) import Control.Category ((>>>))-import Data.Functor.Contravariant (Contravariant (..))+import Data.Bool (bool)+import Data.Foldable (traverse_)+import Data.Functor.Contravariant (Contravariant (..), (>$<)) import Debug.Trace (traceM) import qualified Control.Tracer.Arrow as Arrow@@ -174,6 +183,11 @@ mappend = (<>) mempty = nullTracer +-- | Make an emitting tracer from a callback.+--+mkTracer :: Applicative m => (a -> m ()) -> Tracer m a+mkTracer = Tracer . Arrow.emit+ {-# INLINE traceWith #-} -- | Run a tracer with a given input. traceWith :: Monad m => Tracer m a -> a -> m ()@@ -219,10 +233,30 @@ where classify = arr (maybe (Left ()) Right . k) +-- | A monadic version of `traceMaybe`.+--+traceMaybeM :: Monad m => (a -> m (Maybe b)) -> Tracer m b -> Tracer m a+traceMaybeM k tr = Tracer $ classify >>> (Arrow.squelch ||| use tr)+ where+ classify = Arrow.effect (fmap (maybe (Left ()) Right) . k)+ -- | Uses 'traceMaybe' to give a tracer which emits only if a predicate is true. squelchUnless :: Monad m => (a -> Bool) -> Tracer m a -> Tracer m a-squelchUnless p = traceMaybe (\a -> if p a then Just a else Nothing)+squelchUnless p = traceMaybe (\a -> bool Nothing (Just a) (p a)) +-- | A monadic version of `squelchUnless`.+squelchUnlessM :: Monad m => (a -> m Bool) -> Tracer m a -> Tracer m a+squelchUnlessM p = traceMaybeM (\a -> bool Nothing (Just a) <$> p a)++traceTraversable :: (Monad m, Foldable t) => Tracer m a -> Tracer m (t a)+traceTraversable tracer@(Tracer tr) =+ case tr of+ Arrow.Squelching _ -> nullTracer+ _ -> emit (traverse_ (traceWith tracer))++traceAll :: (Monad m, Foldable t) => (b -> t a) -> Tracer m a -> Tracer m b+traceAll f = contramap f . traceTraversable+ -- | Use a natural transformation to change the @m@ type. This is useful, for -- instance, to use concrete IO tracers in monad transformer stacks that have -- IO as their base.@@ -238,3 +272,13 @@ -- documentation in "Debug.Trace" for more details. debugTracer :: Applicative m => Tracer m String debugTracer = emit traceM++-- | A contravariant transformation of a tracer using a Kleisli arrow.+--+contramapM+ :: Monad m+ => (a -> m b)+ -- ^ Kleisli arrow which is evaluated only if a downstream tracer emits+ -> Tracer m b+ -> Tracer m a+contramapM f tracer = arrow (Arrow.effect f >>> use tracer)
+ src/Test/Control/Tracer/Properties.hs view
@@ -0,0 +1,56 @@+{-|+Module : Test.Control.Tracer.Properties+Description : Various essential properties for Tracer+Copyright : (c) Alexander Vieth, 2019+Licence : BSD3+Maintainer : aovieth@gmail.com+Stability : experimental+Portability : non-portable (GHC only)+-}++{-# LANGUAGE Arrows #-}++module Test.Control.Tracer.Properties where++import Control.Arrow+import Control.Tracer++-- | Does not force the @error "failure"@ used within it, as it's not needed.+--+-- @traceWith laziness_1 anything = pure ()@+laziness_1 :: Monad m => Tracer m a+laziness_1 = arrow $ proc _ -> do+ _ <- arr not -< error "failure"+ returnA -< ()++-- | Simple choice: if both of 2 alternatives do not emit, nothing is forced.+-- +-- @traceWith laziness_2 anything = pure ()@+laziness_2 :: Monad m => Tracer m a+laziness_2 = arrow $ arr (error "failure") >>> (use nullTracer ||| use nullTracer)++-- | Nested choice: even though the first choice _could_ emit, the second+-- choice can't, so nothing after the first choice is forced.+--+-- @traceWith laziness_3 anything = pure ()@+laziness_3 :: Monad m => Tracer m Bool+laziness_3 = arrow $ proc b ->+ if b+ then emit (const (pure ())) -< ()+ else do+ _ <- effect (error "failure") -< error "failure"+ _ <- use nullTracer ||| use nullTracer -< error "failure"+ returnA -< ()++-- | If the inner tracer is null, traversing should not force the structure.+--+-- @traceWith traceTraversable_laziness anything = pure ()@+traceTraversable_laziness :: Monad m => Tracer m [a]+traceTraversable_laziness = traceTraversable nullTracer++-- | If the inner tracer is null, mapping into a foldable should not+-- force the mapped structure.+--+-- @traceWith traceAll_laziness anything = pure ()@+traceAll_laziness :: Monad m => Tracer m Bool+traceAll_laziness = traceAll (\_ -> (error "failure" :: [()])) nullTracer
+ test/Main.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Main where++import Control.Exception (SomeException, try)+import Control.Tracer (traceWith)+import Test.Control.Tracer.Properties+ ( laziness_1+ , laziness_2+ , laziness_3+ , traceTraversable_laziness+ , traceAll_laziness)++assertNoException :: String -> IO a -> IO ()+assertNoException name action = do+ result <- try action+ case result of+ Left (e :: SomeException) ->+ error ("FAILED: " ++ name ++ "\n unexpected exception: " ++ show e)+ Right _ ->+ putStrLn ("PASS: " ++ name)++main :: IO ()+main = do+ assertNoException "laziness_1" $+ traceWith laziness_1 (error "failure")++ assertNoException "laziness_2" $+ traceWith laziness_2 (error "failure")++ assertNoException "laziness_3" $+ traceWith laziness_3 False++ assertNoException "traceTraversable_laziness" $+ traceWith traceTraversable_laziness (error "failure")++ assertNoException "traceAll_laziness" $+ traceWith traceAll_laziness True