    {-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}

    -- |
    -- This package provides the choice operator ('||>') for
    -- lifted IO monad.

    module Control.Exception.IOChoice.Lifted where

    import Control.Exception (IOException)
    import qualified Control.Exception.Lifted as L (catch, throwIO)
    import Control.Monad.Base (MonadBase)
    import Control.Monad.IO.Class
    import Control.Monad.Trans.Control (MonadBaseControl)

    -- |
    -- If 'IOException' occurs or 'goNext' is used in the left monad,
    -- then the right monad is performed. Note that 'fail'
    -- throws 'IOException'.

    (||>) :: MonadBaseControl IO m => m a -> m a -> m a
    x ||> y = x `L.catch` (\(_ :: IOException) -> y)

    infixr 3 ||>

    -- | Go to the next 'IO' monad by throwing 'IOException'.
    goNext :: (MonadIO m, MonadBase IO m) => m a
    goNext = L.throwIO $ userError "goNext for lifted IO"

    -- | Run any one lifted 'IO' monad.
    runAnyOne :: (MonadIO m, MonadBaseControl IO m) => [m a] -> m a
    runAnyOne = foldr (||>) goNext