{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}
module Control.Carrier.Trace.Returning
(
runTrace
, TraceC(..)
, module Control.Effect.Trace
) where
import Control.Algebra
import Control.Applicative (Alternative(..))
import Control.Carrier.Writer.Strict
import Control.Effect.Trace
import Control.Monad (MonadPlus(..))
import qualified Control.Monad.Fail as Fail
import Control.Monad.Fix
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Data.Bifunctor (first)
import Data.Monoid (Endo(..))
runTrace :: Functor m => TraceC m a -> m ([String], a)
runTrace (TraceC m) = first (($[]) . appEndo) <$> runWriter m
newtype TraceC m a = TraceC (WriterC (Endo [String]) m a)
deriving (Alternative, Applicative, Functor, Monad, Fail.MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans)
instance (Algebra sig m, Effect sig) => Algebra (Trace :+: sig) (TraceC m) where
alg (L (Trace m k)) = TraceC (tell (Endo (m :))) *> k
alg (R other) = TraceC (alg (R (handleCoercible other)))