{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
module Control.Tracer
( Tracer (..)
, mkTracer
, traceWith
, arrow
, use
, Arrow.squelch
, Arrow.emit
, Arrow.effect
, nullTracer
, stdoutTracer
, debugTracer
, natTracer
, Arrow.nat
, traceMaybe
, traceMaybeM
, traceAll
, traceTraversable
, squelchUnless
, squelchUnlessM
, Contravariant(..)
, (>$<)
, contramapM
) where
import Control.Arrow ((|||), (&&&), arr, runKleisli)
import Control.Category ((>>>))
import Data.Bool (bool)
import Data.Foldable (traverse_)
import Data.Functor.Contravariant (Contravariant (..), (>$<))
import Debug.Trace (traceM)
import qualified Control.Tracer.Arrow as Arrow
newtype Tracer m a = Tracer { forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
runTracer :: Arrow.TracerA m a () }
instance Monad m => Contravariant (Tracer m) where
contramap :: forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
contramap a' -> a
f !Tracer m a
tracer = TracerA m a' () -> Tracer m a'
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer (TracerA m a' () -> Tracer m a') -> TracerA m a' () -> Tracer m a'
forall a b. (a -> b) -> a -> b
$! ((a' -> a) -> TracerA m a' a
forall b c. (b -> c) -> TracerA m b c
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr a' -> a
f TracerA m a' a -> TracerA m a () -> TracerA m a' ()
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Tracer m a -> TracerA m a ()
forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
use Tracer m a
tracer)
instance Monad m => Semigroup (Tracer m s) where
Tracer TracerA m s ()
a1 <> :: Tracer m s -> Tracer m s -> Tracer m s
<> Tracer TracerA m s ()
a2 = TracerA m s () -> Tracer m s
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer (TracerA m s ()
a1 TracerA m s () -> TracerA m s () -> TracerA m s ((), ())
forall b c c'.
TracerA m b c -> TracerA m b c' -> TracerA m b (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& TracerA m s ()
a2 TracerA m s ((), ()) -> TracerA m ((), ()) () -> TracerA m s ()
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> (((), ()) -> ()) -> TracerA m ((), ()) ()
forall b c. (b -> c) -> TracerA m b c
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr ((), ()) -> ()
discard)
where
discard :: ((), ()) -> ()
discard :: ((), ()) -> ()
discard = () -> ((), ()) -> ()
forall a b. a -> b -> a
const ()
instance Monad m => Monoid (Tracer m s) where
mappend :: Tracer m s -> Tracer m s -> Tracer m s
mappend = Tracer m s -> Tracer m s -> Tracer m s
forall a. Semigroup a => a -> a -> a
(<>)
mempty :: Tracer m s
mempty = Tracer m s
forall (m :: * -> *) s. Monad m => Tracer m s
nullTracer
mkTracer :: Applicative m => (a -> m ()) -> Tracer m a
mkTracer :: forall (m :: * -> *) a. Applicative m => (a -> m ()) -> Tracer m a
mkTracer = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer (TracerA m a () -> Tracer m a)
-> ((a -> m ()) -> TracerA m a ()) -> (a -> m ()) -> Tracer m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> m ()) -> TracerA m a ()
forall (m :: * -> *) a.
Applicative m =>
(a -> m ()) -> TracerA m a ()
Arrow.emit
{-# INLINE traceWith #-}
traceWith :: Monad m => Tracer m a -> a -> m ()
traceWith :: forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith (Tracer TracerA m a ()
tr) a
a = Kleisli m a () -> a -> m ()
forall (m :: * -> *) a b. Kleisli m a b -> a -> m b
runKleisli (TracerA m a () -> Kleisli m a ()
forall (m :: * -> *) a. Monad m => TracerA m a () -> Kleisli m a ()
Arrow.runTracerA TracerA m a ()
tr) a
a
arrow :: Arrow.TracerA m a () -> Tracer m a
arrow :: forall (m :: * -> *) a. TracerA m a () -> Tracer m a
arrow = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer
use :: Tracer m a -> Arrow.TracerA m a ()
use :: forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
use = Tracer m a -> TracerA m a ()
forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
runTracer
nullTracer :: Monad m => Tracer m a
nullTracer :: forall (m :: * -> *) s. Monad m => Tracer m s
nullTracer = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer TracerA m a ()
forall (m :: * -> *) a. Applicative m => TracerA m a ()
Arrow.squelch
emit :: Applicative m => (a -> m ()) -> Tracer m a
emit :: forall (m :: * -> *) a. Applicative m => (a -> m ()) -> Tracer m a
emit a -> m ()
f = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer ((a -> m ()) -> TracerA m a ()
forall (m :: * -> *) a.
Applicative m =>
(a -> m ()) -> TracerA m a ()
Arrow.emit a -> m ()
f)
traceMaybe :: Monad m => (a -> Maybe b) -> Tracer m b -> Tracer m a
traceMaybe :: forall (m :: * -> *) a b.
Monad m =>
(a -> Maybe b) -> Tracer m b -> Tracer m a
traceMaybe a -> Maybe b
k Tracer m b
tr = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer (TracerA m a () -> Tracer m a) -> TracerA m a () -> Tracer m a
forall a b. (a -> b) -> a -> b
$ TracerA m a (Either () b)
classify TracerA m a (Either () b)
-> TracerA m (Either () b) () -> TracerA m a ()
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> (TracerA m () ()
forall (m :: * -> *) a. Applicative m => TracerA m a ()
Arrow.squelch TracerA m () () -> TracerA m b () -> TracerA m (Either () b) ()
forall b d c.
TracerA m b d -> TracerA m c d -> TracerA m (Either b c) d
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| Tracer m b -> TracerA m b ()
forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
use Tracer m b
tr)
where
classify :: TracerA m a (Either () b)
classify = (a -> Either () b) -> TracerA m a (Either () b)
forall b c. (b -> c) -> TracerA m b c
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr (Either () b -> (b -> Either () b) -> Maybe b -> Either () b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> Either () b
forall a b. a -> Either a b
Left ()) b -> Either () b
forall a b. b -> Either a b
Right (Maybe b -> Either () b) -> (a -> Maybe b) -> a -> Either () b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe b
k)
traceMaybeM :: Monad m => (a -> m (Maybe b)) -> Tracer m b -> Tracer m a
traceMaybeM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m (Maybe b)) -> Tracer m b -> Tracer m a
traceMaybeM a -> m (Maybe b)
k Tracer m b
tr = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer (TracerA m a () -> Tracer m a) -> TracerA m a () -> Tracer m a
forall a b. (a -> b) -> a -> b
$ TracerA m a (Either () b)
classify TracerA m a (Either () b)
-> TracerA m (Either () b) () -> TracerA m a ()
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> (TracerA m () ()
forall (m :: * -> *) a. Applicative m => TracerA m a ()
Arrow.squelch TracerA m () () -> TracerA m b () -> TracerA m (Either () b) ()
forall b d c.
TracerA m b d -> TracerA m c d -> TracerA m (Either b c) d
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| Tracer m b -> TracerA m b ()
forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
use Tracer m b
tr)
where
classify :: TracerA m a (Either () b)
classify = (a -> m (Either () b)) -> TracerA m a (Either () b)
forall a (m :: * -> *) b. (a -> m b) -> TracerA m a b
Arrow.effect ((Maybe b -> Either () b) -> m (Maybe b) -> m (Either () b)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Either () b -> (b -> Either () b) -> Maybe b -> Either () b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> Either () b
forall a b. a -> Either a b
Left ()) b -> Either () b
forall a b. b -> Either a b
Right) (m (Maybe b) -> m (Either () b))
-> (a -> m (Maybe b)) -> a -> m (Either () b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m (Maybe b)
k)
squelchUnless :: Monad m => (a -> Bool) -> Tracer m a -> Tracer m a
squelchUnless :: forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> Tracer m a -> Tracer m a
squelchUnless a -> Bool
p = (a -> Maybe a) -> Tracer m a -> Tracer m a
forall (m :: * -> *) a b.
Monad m =>
(a -> Maybe b) -> Tracer m b -> Tracer m a
traceMaybe (\a
a -> Maybe a -> Maybe a -> Bool -> Maybe a
forall a. a -> a -> Bool -> a
bool Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just a
a) (a -> Bool
p a
a))
squelchUnlessM :: Monad m => (a -> m Bool) -> Tracer m a -> Tracer m a
squelchUnlessM :: forall (m :: * -> *) a.
Monad m =>
(a -> m Bool) -> Tracer m a -> Tracer m a
squelchUnlessM a -> m Bool
p = (a -> m (Maybe a)) -> Tracer m a -> Tracer m a
forall (m :: * -> *) a b.
Monad m =>
(a -> m (Maybe b)) -> Tracer m b -> Tracer m a
traceMaybeM (\a
a -> Maybe a -> Maybe a -> Bool -> Maybe a
forall a. a -> a -> Bool -> a
bool Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just a
a) (Bool -> Maybe a) -> m Bool -> m (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> m Bool
p a
a)
traceTraversable :: (Monad m, Foldable t) => Tracer m a -> Tracer m (t a)
traceTraversable :: forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Foldable t) =>
Tracer m a -> Tracer m (t a)
traceTraversable tracer :: Tracer m a
tracer@(Tracer TracerA m a ()
tr) =
case TracerA m a ()
tr of
Arrow.Squelching Kleisli m a ()
_ -> Tracer m (t a)
forall (m :: * -> *) s. Monad m => Tracer m s
nullTracer
TracerA m a ()
_ -> (t a -> m ()) -> Tracer m (t a)
forall (m :: * -> *) a. Applicative m => (a -> m ()) -> Tracer m a
emit ((a -> m ()) -> t a -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Tracer m a -> a -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m a
tracer))
traceAll :: (Monad m, Foldable t) => (b -> t a) -> Tracer m a -> Tracer m b
traceAll :: forall (m :: * -> *) (t :: * -> *) b a.
(Monad m, Foldable t) =>
(b -> t a) -> Tracer m a -> Tracer m b
traceAll b -> t a
f = (b -> t a) -> Tracer m (t a) -> Tracer m b
forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap b -> t a
f (Tracer m (t a) -> Tracer m b)
-> (Tracer m a -> Tracer m (t a)) -> Tracer m a -> Tracer m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tracer m a -> Tracer m (t a)
forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Foldable t) =>
Tracer m a -> Tracer m (t a)
traceTraversable
natTracer :: forall m n s . (forall x . m x -> n x) -> Tracer m s -> Tracer n s
natTracer :: forall (m :: * -> *) (n :: * -> *) s.
(forall x. m x -> n x) -> Tracer m s -> Tracer n s
natTracer forall x. m x -> n x
h (Tracer TracerA m s ()
tr) = TracerA n s () -> Tracer n s
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
Tracer ((forall x. m x -> n x) -> TracerA m s () -> TracerA n s ()
forall (m :: * -> *) (n :: * -> *) a b.
(forall x. m x -> n x) -> TracerA m a b -> TracerA n a b
Arrow.nat m x -> n x
forall x. m x -> n x
h TracerA m s ()
tr)
stdoutTracer :: Tracer IO String
stdoutTracer :: Tracer IO String
stdoutTracer = (String -> IO ()) -> Tracer IO String
forall (m :: * -> *) a. Applicative m => (a -> m ()) -> Tracer m a
emit String -> IO ()
putStrLn
debugTracer :: Applicative m => Tracer m String
debugTracer :: forall (m :: * -> *). Applicative m => Tracer m String
debugTracer = (String -> m ()) -> Tracer m String
forall (m :: * -> *) a. Applicative m => (a -> m ()) -> Tracer m a
emit String -> m ()
forall (f :: * -> *). Applicative f => String -> f ()
traceM
contramapM
:: Monad m
=> (a -> m b)
-> Tracer m b
-> Tracer m a
contramapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Tracer m b -> Tracer m a
contramapM a -> m b
f Tracer m b
tracer = TracerA m a () -> Tracer m a
forall (m :: * -> *) a. TracerA m a () -> Tracer m a
arrow ((a -> m b) -> TracerA m a b
forall a (m :: * -> *) b. (a -> m b) -> TracerA m a b
Arrow.effect a -> m b
f TracerA m a b -> TracerA m b () -> TracerA m a ()
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Tracer m b -> TracerA m b ()
forall (m :: * -> *) a. Tracer m a -> TracerA m a ()
use Tracer m b
tracer)