{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DerivingStrategies #-}
{- |
This module provides a generic output type for multilingual output as well as
a writer monad transformer which has the ability to abort execution.
-}
module Control.OutputCapable.Blocks.Report.Generic (
  GenericOut (..),
  GenericReportT (..),
  alignOutput,
  combineReports,
  combineTwoReports,
  getAllOuts,
  getOutsWithResult,
  toAbort,
  toOutput,
  ) where

import Control.Applicative              (Alternative)
import Control.Monad                    (void)
import Control.Monad.Catch              (MonadCatch (catch), MonadThrow (throwM))
import Control.Monad.IO.Class           (MonadIO)
import Control.Monad.Trans              (MonadTrans (lift))
import Control.Monad.Trans.Maybe (MaybeT (MaybeT, runMaybeT))
import Control.Monad.Writer (
  MonadWriter (tell),
  WriterT (WriterT, runWriterT),
  execWriterT,
  )
import Data.Bifunctor                   (second)
import Data.List.HT                     (takeUntil)
import Data.Maybe                       (isNothing)

data GenericOut l o =
  Format o |
  Localised (l -> o)
  deriving (forall a b. (a -> b) -> GenericOut l a -> GenericOut l b)
-> (forall a b. a -> GenericOut l b -> GenericOut l a)
-> Functor (GenericOut l)
forall a b. a -> GenericOut l b -> GenericOut l a
forall a b. (a -> b) -> GenericOut l a -> GenericOut l b
forall l a b. a -> GenericOut l b -> GenericOut l a
forall l a b. (a -> b) -> GenericOut l a -> GenericOut l b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall l a b. (a -> b) -> GenericOut l a -> GenericOut l b
fmap :: forall a b. (a -> b) -> GenericOut l a -> GenericOut l b
$c<$ :: forall l a b. a -> GenericOut l b -> GenericOut l a
<$ :: forall a b. a -> GenericOut l b -> GenericOut l a
Functor

newtype GenericReportT l o m r =
  Report { forall l o (m :: * -> *) r.
GenericReportT l o m r -> MaybeT (WriterT [GenericOut l o] m) r
unReport :: MaybeT (WriterT [GenericOut l o] m) r }
  deriving newtype (Applicative (GenericReportT l o m)
Applicative (GenericReportT l o m) =>
(forall a. GenericReportT l o m a)
-> (forall a.
    GenericReportT l o m a
    -> GenericReportT l o m a -> GenericReportT l o m a)
-> (forall a. GenericReportT l o m a -> GenericReportT l o m [a])
-> (forall a. GenericReportT l o m a -> GenericReportT l o m [a])
-> Alternative (GenericReportT l o m)
forall a. GenericReportT l o m a
forall a. GenericReportT l o m a -> GenericReportT l o m [a]
forall a.
GenericReportT l o m a
-> GenericReportT l o m a -> GenericReportT l o m a
forall l o (m :: * -> *).
Monad m =>
Applicative (GenericReportT l o m)
forall l o (m :: * -> *) a. Monad m => GenericReportT l o m a
forall l o (m :: * -> *) a.
Monad m =>
GenericReportT l o m a -> GenericReportT l o m [a]
forall l o (m :: * -> *) a.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m a -> GenericReportT l o m a
forall (f :: * -> *).
Applicative f =>
(forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
$cempty :: forall l o (m :: * -> *) a. Monad m => GenericReportT l o m a
empty :: forall a. GenericReportT l o m a
$c<|> :: forall l o (m :: * -> *) a.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m a -> GenericReportT l o m a
<|> :: forall a.
GenericReportT l o m a
-> GenericReportT l o m a -> GenericReportT l o m a
$csome :: forall l o (m :: * -> *) a.
Monad m =>
GenericReportT l o m a -> GenericReportT l o m [a]
some :: forall a. GenericReportT l o m a -> GenericReportT l o m [a]
$cmany :: forall l o (m :: * -> *) a.
Monad m =>
GenericReportT l o m a -> GenericReportT l o m [a]
many :: forall a. GenericReportT l o m a -> GenericReportT l o m [a]
Alternative, Functor (GenericReportT l o m)
Functor (GenericReportT l o m) =>
(forall a. a -> GenericReportT l o m a)
-> (forall a b.
    GenericReportT l o m (a -> b)
    -> GenericReportT l o m a -> GenericReportT l o m b)
-> (forall a b c.
    (a -> b -> c)
    -> GenericReportT l o m a
    -> GenericReportT l o m b
    -> GenericReportT l o m c)
-> (forall a b.
    GenericReportT l o m a
    -> GenericReportT l o m b -> GenericReportT l o m b)
-> (forall a b.
    GenericReportT l o m a
    -> GenericReportT l o m b -> GenericReportT l o m a)
-> Applicative (GenericReportT l o m)
forall a. a -> GenericReportT l o m a
forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m a
forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
forall a b.
GenericReportT l o m (a -> b)
-> GenericReportT l o m a -> GenericReportT l o m b
forall a b c.
(a -> b -> c)
-> GenericReportT l o m a
-> GenericReportT l o m b
-> GenericReportT l o m c
forall l o (m :: * -> *). Monad m => Functor (GenericReportT l o m)
forall l o (m :: * -> *) a. Monad m => a -> GenericReportT l o m a
forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m a
forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m (a -> b)
-> GenericReportT l o m a -> GenericReportT l o m b
forall l o (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> GenericReportT l o m a
-> GenericReportT l o m b
-> GenericReportT l o m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall l o (m :: * -> *) a. Monad m => a -> GenericReportT l o m a
pure :: forall a. a -> GenericReportT l o m a
$c<*> :: forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m (a -> b)
-> GenericReportT l o m a -> GenericReportT l o m b
<*> :: forall a b.
GenericReportT l o m (a -> b)
-> GenericReportT l o m a -> GenericReportT l o m b
$cliftA2 :: forall l o (m :: * -> *) a b c.
Monad m =>
(a -> b -> c)
-> GenericReportT l o m a
-> GenericReportT l o m b
-> GenericReportT l o m c
liftA2 :: forall a b c.
(a -> b -> c)
-> GenericReportT l o m a
-> GenericReportT l o m b
-> GenericReportT l o m c
$c*> :: forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
*> :: forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
$c<* :: forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m a
<* :: forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m a
Applicative, (forall a b.
 (a -> b) -> GenericReportT l o m a -> GenericReportT l o m b)
-> (forall a b.
    a -> GenericReportT l o m b -> GenericReportT l o m a)
-> Functor (GenericReportT l o m)
forall a b. a -> GenericReportT l o m b -> GenericReportT l o m a
forall a b.
(a -> b) -> GenericReportT l o m a -> GenericReportT l o m b
forall l o (m :: * -> *) a b.
Functor m =>
a -> GenericReportT l o m b -> GenericReportT l o m a
forall l o (m :: * -> *) a b.
Functor m =>
(a -> b) -> GenericReportT l o m a -> GenericReportT l o m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall l o (m :: * -> *) a b.
Functor m =>
(a -> b) -> GenericReportT l o m a -> GenericReportT l o m b
fmap :: forall a b.
(a -> b) -> GenericReportT l o m a -> GenericReportT l o m b
$c<$ :: forall l o (m :: * -> *) a b.
Functor m =>
a -> GenericReportT l o m b -> GenericReportT l o m a
<$ :: forall a b. a -> GenericReportT l o m b -> GenericReportT l o m a
Functor, Applicative (GenericReportT l o m)
Applicative (GenericReportT l o m) =>
(forall a b.
 GenericReportT l o m a
 -> (a -> GenericReportT l o m b) -> GenericReportT l o m b)
-> (forall a b.
    GenericReportT l o m a
    -> GenericReportT l o m b -> GenericReportT l o m b)
-> (forall a. a -> GenericReportT l o m a)
-> Monad (GenericReportT l o m)
forall a. a -> GenericReportT l o m a
forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
forall a b.
GenericReportT l o m a
-> (a -> GenericReportT l o m b) -> GenericReportT l o m b
forall l o (m :: * -> *).
Monad m =>
Applicative (GenericReportT l o m)
forall l o (m :: * -> *) a. Monad m => a -> GenericReportT l o m a
forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> (a -> GenericReportT l o m b) -> GenericReportT l o m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> (a -> GenericReportT l o m b) -> GenericReportT l o m b
>>= :: forall a b.
GenericReportT l o m a
-> (a -> GenericReportT l o m b) -> GenericReportT l o m b
$c>> :: forall l o (m :: * -> *) a b.
Monad m =>
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
>> :: forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
$creturn :: forall l o (m :: * -> *) a. Monad m => a -> GenericReportT l o m a
return :: forall a. a -> GenericReportT l o m a
Monad, Monad (GenericReportT l o m)
Monad (GenericReportT l o m) =>
(forall a. IO a -> GenericReportT l o m a)
-> MonadIO (GenericReportT l o m)
forall a. IO a -> GenericReportT l o m a
forall l o (m :: * -> *). MonadIO m => Monad (GenericReportT l o m)
forall l o (m :: * -> *) a.
MonadIO m =>
IO a -> GenericReportT l o m a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
$cliftIO :: forall l o (m :: * -> *) a.
MonadIO m =>
IO a -> GenericReportT l o m a
liftIO :: forall a. IO a -> GenericReportT l o m a
MonadIO)

instance MonadTrans (GenericReportT l o) where
  lift :: forall (m :: * -> *) a. Monad m => m a -> GenericReportT l o m a
lift m a
m = MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a)
-> MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a
forall a b. (a -> b) -> a -> b
$ WriterT [GenericOut l o] m (Maybe a)
-> MaybeT (WriterT [GenericOut l o] m) a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe a)
 -> MaybeT (WriterT [GenericOut l o] m) a)
-> WriterT [GenericOut l o] m (Maybe a)
-> MaybeT (WriterT [GenericOut l o] m) a
forall a b. (a -> b) -> a -> b
$ m (Maybe a, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe a)
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterT (m (Maybe a, [GenericOut l o])
 -> WriterT [GenericOut l o] m (Maybe a))
-> m (Maybe a, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe a)
forall a b. (a -> b) -> a -> b
$ (a -> (Maybe a, [GenericOut l o]))
-> m a -> m (Maybe a, [GenericOut l o])
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a
x -> (a -> Maybe a
forall a. a -> Maybe a
Just a
x, [])) m a
m

instance MonadThrow m => MonadThrow (GenericReportT l o m) where
  throwM :: forall e a.
(HasCallStack, Exception e) =>
e -> GenericReportT l o m a
throwM = m a -> GenericReportT l o m a
forall (m :: * -> *) a. Monad m => m a -> GenericReportT l o m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> GenericReportT l o m a)
-> (e -> m a) -> e -> GenericReportT l o m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> m a
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
throwM

instance MonadCatch m => MonadCatch (GenericReportT l o m) where
  catch :: forall e a.
(HasCallStack, Exception e) =>
GenericReportT l o m a
-> (e -> GenericReportT l o m a) -> GenericReportT l o m a
catch GenericReportT l o m a
x e -> GenericReportT l o m a
f = MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a)
-> MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a
forall a b. (a -> b) -> a -> b
$ WriterT [GenericOut l o] m (Maybe a)
-> MaybeT (WriterT [GenericOut l o] m) a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe a)
 -> MaybeT (WriterT [GenericOut l o] m) a)
-> WriterT [GenericOut l o] m (Maybe a)
-> MaybeT (WriterT [GenericOut l o] m) a
forall a b. (a -> b) -> a -> b
$ m (Maybe a, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe a)
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterT (m (Maybe a, [GenericOut l o])
 -> WriterT [GenericOut l o] m (Maybe a))
-> m (Maybe a, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe a)
forall a b. (a -> b) -> a -> b
$ m (Maybe a, [GenericOut l o])
-> (e -> m (Maybe a, [GenericOut l o]))
-> m (Maybe a, [GenericOut l o])
forall e a. (HasCallStack, Exception e) => m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(MonadCatch m, HasCallStack, Exception e) =>
m a -> (e -> m a) -> m a
catch
    (WriterT [GenericOut l o] m (Maybe a)
-> m (Maybe a, [GenericOut l o])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (WriterT [GenericOut l o] m (Maybe a)
 -> m (Maybe a, [GenericOut l o]))
-> (GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a))
-> GenericReportT l o m a
-> m (Maybe a, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaybeT (WriterT [GenericOut l o] m) a
-> WriterT [GenericOut l o] m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT (WriterT [GenericOut l o] m) a
 -> WriterT [GenericOut l o] m (Maybe a))
-> (GenericReportT l o m a
    -> MaybeT (WriterT [GenericOut l o] m) a)
-> GenericReportT l o m a
-> WriterT [GenericOut l o] m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenericReportT l o m a -> MaybeT (WriterT [GenericOut l o] m) a
forall l o (m :: * -> *) r.
GenericReportT l o m r -> MaybeT (WriterT [GenericOut l o] m) r
unReport (GenericReportT l o m a -> m (Maybe a, [GenericOut l o]))
-> GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
forall a b. (a -> b) -> a -> b
$ GenericReportT l o m a
x)
    (WriterT [GenericOut l o] m (Maybe a)
-> m (Maybe a, [GenericOut l o])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (WriterT [GenericOut l o] m (Maybe a)
 -> m (Maybe a, [GenericOut l o]))
-> (e -> WriterT [GenericOut l o] m (Maybe a))
-> e
-> m (Maybe a, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaybeT (WriterT [GenericOut l o] m) a
-> WriterT [GenericOut l o] m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT (WriterT [GenericOut l o] m) a
 -> WriterT [GenericOut l o] m (Maybe a))
-> (e -> MaybeT (WriterT [GenericOut l o] m) a)
-> e
-> WriterT [GenericOut l o] m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenericReportT l o m a -> MaybeT (WriterT [GenericOut l o] m) a
forall l o (m :: * -> *) r.
GenericReportT l o m r -> MaybeT (WriterT [GenericOut l o] m) r
unReport (GenericReportT l o m a -> MaybeT (WriterT [GenericOut l o] m) a)
-> (e -> GenericReportT l o m a)
-> e
-> MaybeT (WriterT [GenericOut l o] m) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> GenericReportT l o m a
f)

getOutsWithResult
  :: GenericReportT l o m a
  -> m (Maybe a, [GenericOut l o])
getOutsWithResult :: forall l o (m :: * -> *) a.
GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
getOutsWithResult = WriterT [GenericOut l o] m (Maybe a)
-> m (Maybe a, [GenericOut l o])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (WriterT [GenericOut l o] m (Maybe a)
 -> m (Maybe a, [GenericOut l o]))
-> (GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a))
-> GenericReportT l o m a
-> m (Maybe a, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a)
forall l o (m :: * -> *) a.
GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a)
getAllOuts'

getAllOuts :: Monad m => GenericReportT l o m a -> m [GenericOut l o]
getAllOuts :: forall (m :: * -> *) l o a.
Monad m =>
GenericReportT l o m a -> m [GenericOut l o]
getAllOuts = WriterT [GenericOut l o] m (Maybe a) -> m [GenericOut l o]
forall (m :: * -> *) w a. Monad m => WriterT w m a -> m w
execWriterT (WriterT [GenericOut l o] m (Maybe a) -> m [GenericOut l o])
-> (GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a))
-> GenericReportT l o m a
-> m [GenericOut l o]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a)
forall l o (m :: * -> *) a.
GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a)
getAllOuts'

getAllOuts'
  :: GenericReportT l o m a
  -> WriterT [GenericOut l o] m (Maybe a)
getAllOuts' :: forall l o (m :: * -> *) a.
GenericReportT l o m a -> WriterT [GenericOut l o] m (Maybe a)
getAllOuts' GenericReportT l o m a
r = MaybeT (WriterT [GenericOut l o] m) a
-> WriterT [GenericOut l o] m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT (WriterT [GenericOut l o] m) a
 -> WriterT [GenericOut l o] m (Maybe a))
-> MaybeT (WriterT [GenericOut l o] m) a
-> WriterT [GenericOut l o] m (Maybe a)
forall a b. (a -> b) -> a -> b
$ GenericReportT l o m a -> MaybeT (WriterT [GenericOut l o] m) a
forall l o (m :: * -> *) r.
GenericReportT l o m r -> MaybeT (WriterT [GenericOut l o] m) r
unReport GenericReportT l o m a
r

{-|
Combines the output of the list of given reports using the provided function.
Output is provided for all reports up to including the first failing report.
-}
combineReports
  :: Monad m
  => ([[o]] -> o)
  -> [GenericReportT l o m a]
  -> GenericReportT l o m ()
combineReports :: forall (m :: * -> *) o l a.
Monad m =>
([[o]] -> o) -> [GenericReportT l o m a] -> GenericReportT l o m ()
combineReports [[o]] -> o
f [GenericReportT l o m a]
rs = MaybeT (WriterT [GenericOut l o] m) () -> GenericReportT l o m ()
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (MaybeT (WriterT [GenericOut l o] m) () -> GenericReportT l o m ())
-> MaybeT (WriterT [GenericOut l o] m) ()
-> GenericReportT l o m ()
forall a b. (a -> b) -> a -> b
$ do
  [(Maybe a, [GenericOut l o])]
rs' <- WriterT [GenericOut l o] m [(Maybe a, [GenericOut l o])]
-> MaybeT
     (WriterT [GenericOut l o] m) [(Maybe a, [GenericOut l o])]
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT [GenericOut l o] m [(Maybe a, [GenericOut l o])]
 -> MaybeT
      (WriterT [GenericOut l o] m) [(Maybe a, [GenericOut l o])])
-> (m [(Maybe a, [GenericOut l o])]
    -> WriterT [GenericOut l o] m [(Maybe a, [GenericOut l o])])
-> m [(Maybe a, [GenericOut l o])]
-> MaybeT
     (WriterT [GenericOut l o] m) [(Maybe a, [GenericOut l o])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m [(Maybe a, [GenericOut l o])]
-> WriterT [GenericOut l o] m [(Maybe a, [GenericOut l o])]
forall (m :: * -> *) a.
Monad m =>
m a -> WriterT [GenericOut l o] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [(Maybe a, [GenericOut l o])]
 -> MaybeT
      (WriterT [GenericOut l o] m) [(Maybe a, [GenericOut l o])])
-> m [(Maybe a, [GenericOut l o])]
-> MaybeT
     (WriterT [GenericOut l o] m) [(Maybe a, [GenericOut l o])]
forall a b. (a -> b) -> a -> b
$ GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
forall l o (m :: * -> *) a.
GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
getOutsWithResult (GenericReportT l o m a -> m (Maybe a, [GenericOut l o]))
-> [GenericReportT l o m a] -> m [(Maybe a, [GenericOut l o])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
`mapM` [GenericReportT l o m a]
rs
  let maybeOs :: [(Maybe a, [l -> o])]
maybeOs = ((Maybe a, [GenericOut l o]) -> (Maybe a, [l -> o]))
-> [(Maybe a, [GenericOut l o])] -> [(Maybe a, [l -> o])]
forall a b. (a -> b) -> [a] -> [b]
map (([GenericOut l o] -> [l -> o])
-> (Maybe a, [GenericOut l o]) -> (Maybe a, [l -> o])
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ((GenericOut l o -> l -> o) -> [GenericOut l o] -> [l -> o]
forall a b. (a -> b) -> [a] -> [b]
map GenericOut l o -> l -> o
forall l o. GenericOut l o -> l -> o
toOutput)) [(Maybe a, [GenericOut l o])]
rs'
      os :: [[l -> o]]
os = ((Maybe a, [l -> o]) -> [l -> o])
-> [(Maybe a, [l -> o])] -> [[l -> o]]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe a, [l -> o]) -> [l -> o]
forall a b. (a, b) -> b
snd ([(Maybe a, [l -> o])] -> [[l -> o]])
-> [(Maybe a, [l -> o])] -> [[l -> o]]
forall a b. (a -> b) -> a -> b
$ ((Maybe a, [l -> o]) -> Bool)
-> [(Maybe a, [l -> o])] -> [(Maybe a, [l -> o])]
forall a. (a -> Bool) -> [a] -> [a]
takeUntil (Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing (Maybe a -> Bool)
-> ((Maybe a, [l -> o]) -> Maybe a) -> (Maybe a, [l -> o]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe a, [l -> o]) -> Maybe a
forall a b. (a, b) -> a
fst) [(Maybe a, [l -> o])]
maybeOs
  [GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ())
-> ((l -> o) -> [GenericOut l o])
-> (l -> o)
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GenericOut l o -> [GenericOut l o] -> [GenericOut l o]
forall a. a -> [a] -> [a]
:[]) (GenericOut l o -> [GenericOut l o])
-> ((l -> o) -> GenericOut l o) -> (l -> o) -> [GenericOut l o]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (l -> o) -> GenericOut l o
forall l o. (l -> o) -> GenericOut l o
Localised ((l -> o) -> MaybeT (WriterT [GenericOut l o] m) ())
-> (l -> o) -> MaybeT (WriterT [GenericOut l o] m) ()
forall a b. (a -> b) -> a -> b
$ \l
l -> [[o]] -> o
f ([[o]] -> o) -> [[o]] -> o
forall a b. (a -> b) -> a -> b
$ ([l -> o] -> [o]) -> [[l -> o]] -> [[o]]
forall a b. (a -> b) -> [a] -> [b]
map (((l -> o) -> o) -> [l -> o] -> [o]
forall a b. (a -> b) -> [a] -> [b]
map ((l -> o) -> l -> o
forall a b. (a -> b) -> a -> b
$ l
l)) [[l -> o]]
os
  WriterT [GenericOut l o] m (Maybe ())
-> MaybeT (WriterT [GenericOut l o] m) ()
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe ())
 -> MaybeT (WriterT [GenericOut l o] m) ())
-> (Maybe () -> WriterT [GenericOut l o] m (Maybe ()))
-> Maybe ()
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe () -> WriterT [GenericOut l o] m (Maybe ())
forall a. a -> WriterT [GenericOut l o] m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe () -> MaybeT (WriterT [GenericOut l o] m) ())
-> Maybe () -> MaybeT (WriterT [GenericOut l o] m) ()
forall a b. (a -> b) -> a -> b
$ ((Maybe a, [GenericOut l o]) -> Maybe a)
-> [(Maybe a, [GenericOut l o])] -> Maybe ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Maybe a, [GenericOut l o]) -> Maybe a
forall a b. (a, b) -> a
fst [(Maybe a, [GenericOut l o])]
rs'

alignOutput
  :: Monad m
  => ([o] -> o)
  -> GenericReportT l o m a
  -> GenericReportT l o m a
alignOutput :: forall (m :: * -> *) o l a.
Monad m =>
([o] -> o) -> GenericReportT l o m a -> GenericReportT l o m a
alignOutput [o] -> o
f GenericReportT l o m a
r = MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a)
-> MaybeT (WriterT [GenericOut l o] m) a -> GenericReportT l o m a
forall a b. (a -> b) -> a -> b
$ do
  (Maybe a
result, [GenericOut l o]
r') <- WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o])
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
 -> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o]))
-> (GenericReportT l o m a
    -> WriterT [GenericOut l o] m (Maybe a, [GenericOut l o]))
-> GenericReportT l o m a
-> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Maybe a, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
forall (m :: * -> *) a.
Monad m =>
m a -> WriterT [GenericOut l o] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a, [GenericOut l o])
 -> WriterT [GenericOut l o] m (Maybe a, [GenericOut l o]))
-> (GenericReportT l o m a -> m (Maybe a, [GenericOut l o]))
-> GenericReportT l o m a
-> WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
forall l o (m :: * -> *) a.
GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
getOutsWithResult (GenericReportT l o m a
 -> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o]))
-> GenericReportT l o m a
-> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o])
forall a b. (a -> b) -> a -> b
$ GenericReportT l o m a
r
  let xs :: [l -> o]
xs = (GenericOut l o -> l -> o) -> [GenericOut l o] -> [l -> o]
forall a b. (a -> b) -> [a] -> [b]
map GenericOut l o -> l -> o
forall l o. GenericOut l o -> l -> o
toOutput [GenericOut l o]
r'
  [GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ())
-> ((l -> o) -> [GenericOut l o])
-> (l -> o)
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GenericOut l o -> [GenericOut l o] -> [GenericOut l o]
forall a. a -> [a] -> [a]
:[]) (GenericOut l o -> [GenericOut l o])
-> ((l -> o) -> GenericOut l o) -> (l -> o) -> [GenericOut l o]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (l -> o) -> GenericOut l o
forall l o. (l -> o) -> GenericOut l o
Localised ((l -> o) -> MaybeT (WriterT [GenericOut l o] m) ())
-> (l -> o) -> MaybeT (WriterT [GenericOut l o] m) ()
forall a b. (a -> b) -> a -> b
$ \l
l -> [o] -> o
f ([o] -> o) -> [o] -> o
forall a b. (a -> b) -> a -> b
$ ((l -> o) -> o) -> [l -> o] -> [o]
forall a b. (a -> b) -> [a] -> [b]
map ((l -> o) -> l -> o
forall a b. (a -> b) -> a -> b
$ l
l) [l -> o]
xs
  WriterT [GenericOut l o] m (Maybe a)
-> MaybeT (WriterT [GenericOut l o] m) a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe a)
 -> MaybeT (WriterT [GenericOut l o] m) a)
-> (Maybe a -> WriterT [GenericOut l o] m (Maybe a))
-> Maybe a
-> MaybeT (WriterT [GenericOut l o] m) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> WriterT [GenericOut l o] m (Maybe a)
forall a. a -> WriterT [GenericOut l o] m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> MaybeT (WriterT [GenericOut l o] m) a)
-> Maybe a -> MaybeT (WriterT [GenericOut l o] m) a
forall a b. (a -> b) -> a -> b
$ Maybe a
result

toOutput
  :: GenericOut l o
  -> (l -> o)
toOutput :: forall l o. GenericOut l o -> l -> o
toOutput (Format o
x)    = o -> l -> o
forall a b. a -> b -> a
const o
x
toOutput (Localised l -> o
x) = l -> o
x

{-|
Combines the output of the two given reports using the provided functions.

If the execution aborts on the first report the second report is treated
as if has not produced any output.
-}
combineTwoReports
  :: Monad m
  => ([o] -> [o] -> o)
  -> GenericReportT l o m a
  -> GenericReportT l o m b
  -> GenericReportT l o m ()
combineTwoReports :: forall (m :: * -> *) o l a b.
Monad m =>
([o] -> [o] -> o)
-> GenericReportT l o m a
-> GenericReportT l o m b
-> GenericReportT l o m ()
combineTwoReports [o] -> [o] -> o
f GenericReportT l o m a
r1 GenericReportT l o m b
r2 = MaybeT (WriterT [GenericOut l o] m) () -> GenericReportT l o m ()
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (MaybeT (WriterT [GenericOut l o] m) () -> GenericReportT l o m ())
-> MaybeT (WriterT [GenericOut l o] m) ()
-> GenericReportT l o m ()
forall a b. (a -> b) -> a -> b
$ do
  (Maybe a
result1, [GenericOut l o]
r1') <- WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o])
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
 -> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o]))
-> (m (Maybe a, [GenericOut l o])
    -> WriterT [GenericOut l o] m (Maybe a, [GenericOut l o]))
-> m (Maybe a, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Maybe a, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe a, [GenericOut l o])
forall (m :: * -> *) a.
Monad m =>
m a -> WriterT [GenericOut l o] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe a, [GenericOut l o])
 -> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o]))
-> m (Maybe a, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe a, [GenericOut l o])
forall a b. (a -> b) -> a -> b
$ GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
forall l o (m :: * -> *) a.
GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
getOutsWithResult GenericReportT l o m a
r1
  let o1 :: [l -> o]
o1 = (GenericOut l o -> l -> o) -> [GenericOut l o] -> [l -> o]
forall a b. (a -> b) -> [a] -> [b]
map GenericOut l o -> l -> o
forall l o. GenericOut l o -> l -> o
toOutput [GenericOut l o]
r1'
  (Maybe b
result2, [GenericOut l o]
r2') <- WriterT [GenericOut l o] m (Maybe b, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe b, [GenericOut l o])
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT [GenericOut l o] m (Maybe b, [GenericOut l o])
 -> MaybeT (WriterT [GenericOut l o] m) (Maybe b, [GenericOut l o]))
-> (m (Maybe b, [GenericOut l o])
    -> WriterT [GenericOut l o] m (Maybe b, [GenericOut l o]))
-> m (Maybe b, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe b, [GenericOut l o])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Maybe b, [GenericOut l o])
-> WriterT [GenericOut l o] m (Maybe b, [GenericOut l o])
forall (m :: * -> *) a.
Monad m =>
m a -> WriterT [GenericOut l o] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe b, [GenericOut l o])
 -> MaybeT (WriterT [GenericOut l o] m) (Maybe b, [GenericOut l o]))
-> m (Maybe b, [GenericOut l o])
-> MaybeT (WriterT [GenericOut l o] m) (Maybe b, [GenericOut l o])
forall a b. (a -> b) -> a -> b
$ GenericReportT l o m b -> m (Maybe b, [GenericOut l o])
forall l o (m :: * -> *) a.
GenericReportT l o m a -> m (Maybe a, [GenericOut l o])
getOutsWithResult GenericReportT l o m b
r2
  let o2 :: [l -> o]
o2
        | Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing Maybe a
result1 = []
        | Bool
otherwise = (GenericOut l o -> l -> o) -> [GenericOut l o] -> [l -> o]
forall a b. (a -> b) -> [a] -> [b]
map GenericOut l o -> l -> o
forall l o. GenericOut l o -> l -> o
toOutput [GenericOut l o]
r2'
  [GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ())
-> ((l -> o) -> [GenericOut l o])
-> (l -> o)
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GenericOut l o -> [GenericOut l o] -> [GenericOut l o]
forall a. a -> [a] -> [a]
:[]) (GenericOut l o -> [GenericOut l o])
-> ((l -> o) -> GenericOut l o) -> (l -> o) -> [GenericOut l o]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (l -> o) -> GenericOut l o
forall l o. (l -> o) -> GenericOut l o
Localised ((l -> o) -> MaybeT (WriterT [GenericOut l o] m) ())
-> (l -> o) -> MaybeT (WriterT [GenericOut l o] m) ()
forall a b. (a -> b) -> a -> b
$ \l
l -> [o] -> [o] -> o
f (((l -> o) -> o) -> [l -> o] -> [o]
forall a b. (a -> b) -> [a] -> [b]
map ((l -> o) -> l -> o
forall a b. (a -> b) -> a -> b
$ l
l) [l -> o]
o1) ([o] -> o) -> [o] -> o
forall a b. (a -> b) -> a -> b
$ ((l -> o) -> o) -> [l -> o] -> [o]
forall a b. (a -> b) -> [a] -> [b]
map ((l -> o) -> l -> o
forall a b. (a -> b) -> a -> b
$ l
l) [l -> o]
o2
  MaybeT (WriterT [GenericOut l o] m) a
-> MaybeT (WriterT [GenericOut l o] m) ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (MaybeT (WriterT [GenericOut l o] m) a
 -> MaybeT (WriterT [GenericOut l o] m) ())
-> (Maybe a -> MaybeT (WriterT [GenericOut l o] m) a)
-> Maybe a
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WriterT [GenericOut l o] m (Maybe a)
-> MaybeT (WriterT [GenericOut l o] m) a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe a)
 -> MaybeT (WriterT [GenericOut l o] m) a)
-> (Maybe a -> WriterT [GenericOut l o] m (Maybe a))
-> Maybe a
-> MaybeT (WriterT [GenericOut l o] m) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> WriterT [GenericOut l o] m (Maybe a)
forall a. a -> WriterT [GenericOut l o] m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> MaybeT (WriterT [GenericOut l o] m) ())
-> Maybe a -> MaybeT (WriterT [GenericOut l o] m) ()
forall a b. (a -> b) -> a -> b
$ Maybe a
result1
  MaybeT (WriterT [GenericOut l o] m) b
-> MaybeT (WriterT [GenericOut l o] m) ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (MaybeT (WriterT [GenericOut l o] m) b
 -> MaybeT (WriterT [GenericOut l o] m) ())
-> (Maybe b -> MaybeT (WriterT [GenericOut l o] m) b)
-> Maybe b
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WriterT [GenericOut l o] m (Maybe b)
-> MaybeT (WriterT [GenericOut l o] m) b
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe b)
 -> MaybeT (WriterT [GenericOut l o] m) b)
-> (Maybe b -> WriterT [GenericOut l o] m (Maybe b))
-> Maybe b
-> MaybeT (WriterT [GenericOut l o] m) b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe b -> WriterT [GenericOut l o] m (Maybe b)
forall a. a -> WriterT [GenericOut l o] m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe b -> MaybeT (WriterT [GenericOut l o] m) ())
-> Maybe b -> MaybeT (WriterT [GenericOut l o] m) ()
forall a b. (a -> b) -> a -> b
$ Maybe b
result2

toAbort
  :: Monad m
  => GenericReportT l o m a
  -> GenericReportT l o m b
toAbort :: forall (m :: * -> *) l o a b.
Monad m =>
GenericReportT l o m a -> GenericReportT l o m b
toAbort GenericReportT l o m a
r = GenericReportT l o m a
r GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
forall a b.
GenericReportT l o m a
-> GenericReportT l o m b -> GenericReportT l o m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MaybeT (WriterT [GenericOut l o] m) b -> GenericReportT l o m b
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (WriterT [GenericOut l o] m (Maybe b)
-> MaybeT (WriterT [GenericOut l o] m) b
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WriterT [GenericOut l o] m (Maybe b)
 -> MaybeT (WriterT [GenericOut l o] m) b)
-> WriterT [GenericOut l o] m (Maybe b)
-> MaybeT (WriterT [GenericOut l o] m) b
forall a b. (a -> b) -> a -> b
$ Maybe b -> WriterT [GenericOut l o] m (Maybe b)
forall a. a -> WriterT [GenericOut l o] m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe b
forall a. Maybe a
Nothing)