-- | Like the spoon package, but for catching one specific exception
-- type and returning it.

module Control.Spork
    ( spork
    ) where

import Control.Exception
import System.IO.Unsafe

-- | Evaluate `a` and return left if it throws a pure exception.
spork
  :: Exception e
  => a -> Either e a
spork :: forall e a. Exception e => a -> Either e a
spork a
a =
  IO (Either e a) -> Either e a
forall a. IO a -> a
unsafePerformIO (IO (Either e a) -> Either e a) -> IO (Either e a) -> Either e a
forall a b. (a -> b) -> a -> b
$
  (a -> Either e a
forall a b. b -> Either a b
Right (a -> Either e a) -> IO a -> IO (Either e a)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` a -> IO a
forall a. a -> IO a
evaluate a
a) IO (Either e a) -> [Handler (Either e a)] -> IO (Either e a)
forall a. IO a -> [Handler a] -> IO a
`catches` [(e -> IO (Either e a)) -> Handler (Either e a)
forall a e. Exception e => (e -> IO a) -> Handler a
Handler (\e
e -> Either e a -> IO (Either e a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> Either e a
forall a b. a -> Either a b
Left e
e))]
{-# INLINEABLE spork #-}