{-# LANGUAGE RankNTypes #-}

module Plow.Throwing where

import Data.Functor.Contravariant (Contravariant (..))
import Plow.Logging

newtype Thrower m a = Thrower (forall b. a -> m b)

instance Contravariant (Thrower m) where
  contramap :: forall a' a. (a' -> a) -> Thrower m a -> Thrower m a'
contramap a' -> a
f (Thrower forall b. a -> m b
t) = forall (m :: * -> *) a. (forall b. a -> m b) -> Thrower m a
Thrower (forall b. a -> m b
t forall b c a. (b -> c) -> (a -> b) -> a -> c
. a' -> a
f)

throwWith :: Thrower m a -> a -> m b
throwWith :: forall (m :: * -> *) a b. Thrower m a -> a -> m b
throwWith (Thrower forall b. a -> m b
t) a
a = forall b. a -> m b
t a
a

withTracer :: Monad m => Tracer m a -> Thrower m a -> Thrower m a
withTracer :: forall (m :: * -> *) a.
Monad m =>
Tracer m a -> Thrower m a -> Thrower m a
withTracer (Tracer a -> m ()
tr) (Thrower forall b. a -> m b
th) = forall (m :: * -> *) a. (forall b. a -> m b) -> Thrower m a
Thrower forall a b. (a -> b) -> a -> b
$ \a
m -> a -> m ()
tr a
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall b. a -> m b
th a
m