-- |
-- Module: Staversion.Internal.EIO
-- Description: 
-- Maintainer: Toshio Ito <debug.ito@gmail.com>
--
-- __This is an internal module. End-users should not use it.__
module Staversion.Internal.EIO
       ( EIO,
         runEIO,
         toEIO,
         toEIOShow,
         loggedElse,
         maybeToEIO,
         eitherToEIO
       ) where

import Control.Monad.Trans.Except (runExceptT, ExceptT(..))
import qualified Data.Bifunctor as Bi

import Staversion.Internal.Log (Logger, logWarn)
import Staversion.Internal.Query (ErrorMsg)

type EIO = ExceptT ErrorMsg IO

runEIO :: EIO a -> IO (Either ErrorMsg a)
runEIO :: forall a. EIO a -> IO (Either ErrorMsg a)
runEIO = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT

toEIO :: IO (Either ErrorMsg a) -> EIO a
toEIO :: forall a. IO (Either ErrorMsg a) -> EIO a
toEIO = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT

toEIOShow :: Show e => IO (Either e a) -> EIO a
toEIOShow :: forall e a. Show e => IO (Either e a) -> EIO a
toEIOShow = forall a. IO (Either ErrorMsg a) -> EIO a
toEIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
Bi.first forall a. Show a => a -> ErrorMsg
show)

loggedElse :: Logger
           -> EIO a -- ^ first action tried.
           -> EIO a -- ^ the action executed if the first action returns 'Left'.
           -> EIO a
loggedElse :: forall a. Logger -> EIO a -> EIO a -> EIO a
loggedElse Logger
logger EIO a
first EIO a
second = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ do
  Either ErrorMsg a
eret <- forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT EIO a
first
  case Either ErrorMsg a
eret of
   Right a
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return Either ErrorMsg a
eret
   Left ErrorMsg
e -> Logger -> ErrorMsg -> IO ()
logWarn Logger
logger ErrorMsg
e forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT EIO a
second

maybeToEIO :: ErrorMsg -> Maybe a -> EIO a
maybeToEIO :: forall a. ErrorMsg -> Maybe a -> EIO a
maybeToEIO ErrorMsg
msg = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left ErrorMsg
msg) forall a b. b -> Either a b
Right

eitherToEIO :: Either ErrorMsg a -> EIO a
eitherToEIO :: forall a. Either ErrorMsg a -> EIO a
eitherToEIO = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return