serokell-util-0.4.1: src/Serokell/Util/Exceptions.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- | Bitgram's general-purpose exceptions.
-- They may be useful when you need a simple instance of Exception (e. g. in MonadThrow context)
module Serokell.Util.Exceptions
( TextException (..)
, throwText
, EmptyException (..)
, throwEmpty
, eitherToFail
) where
import Universum
import Control.Exception (Exception (..), SomeException)
import qualified Control.Monad as Monad
import Data.Text (Text)
import qualified Data.Text.Buildable
import qualified Data.Text.Format as F
import Data.Typeable (Typeable)
import Formatting (bprint, stext, string, (%))
instance Buildable SomeException where
build e =
case fromException e of
Nothing -> bprint string (displayException e)
Just (TextException msg) -> bprint ("TextException: " %stext) msg
-- | Use this type if you are sure that text description is enough to represent error
newtype TextException = TextException
{ teMessage :: Text
} deriving (Show,Typeable)
instance Exception TextException
instance Buildable TextException where
build = F.build "TextException: {}" . F.Only . teMessage
throwText :: MonadThrow m
=> Text -> m a
throwText = throwM . TextException
-- | Use this type if you want to signal about error and there may be only one reason for it
data EmptyException = EmptyException
deriving (Show, Typeable)
instance Exception EmptyException
throwEmpty :: MonadThrow m => m a
throwEmpty = throwM EmptyException
-- | Convert MonadThrow to arbitrary monad using `fail` to report
-- error Useful when you have `MonadThrow` and want to use it in
-- another monad context which uses `fail` for errors
eitherToFail :: (Monad m, e ~ SomeException) => Either e a -> m a
eitherToFail = either (Monad.fail . show) return