module Scheme.Error
  ( extractValue
  , trapError
  , liftThrows
  , runIOThrows
  ) where

import Scheme.Types
import Control.Monad.Except

-- | Extract a value from an error
extractValue :: ThrowsError a -> a
extractValue (Right val) = val

-- | Trap the error from the given action
trapError :: (MonadError e m, Show e) => m String -> m String
trapError action = catchError action (return . show)

-- | Lift an error throwing thing into the IO-ish monad
liftThrows :: ThrowsError a -> IOThrowsError a
liftThrows (Left err) = throwError err
liftThrows (Right val) = return val

-- | Catch error from IOThrowsError
runIOThrows :: IOThrowsError String -> IO String
runIOThrows action = runExceptT (trapError action) >>= return . extractValue

