alternative-io-0.0.0: Data/Alternative/IO.hs
{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-|
'IO' as 'Alternative' instance.
If the left 'IO' monad of ('<|>') causes an error or 'goNext' is used,
the right 'IO' monad is executed.
Of course, side effects cannot be rolled back. This means
that this 'Alternative' instance breaks the 'Alternative' laws.
But it's common in parsers.
-}
module Data.Alternative.IO where
import Control.Applicative
import Control.Exception
import Data.Typeable
import Prelude hiding (catch)
----------------------------------------------------------------
instance Alternative IO where
empty = goNext
x <|> y = x `catch` (\(_ :: SomeException) -> y)
----------------------------------------------------------------
{-| Go to the next 'IO' monad by throwing 'AltIOgoNext'.
-}
goNext :: IO a
goNext = throwIO AltIOgoNext
{-| Run any one 'IO' monad.
-}
runAnyOne :: [IO a] -> IO a
runAnyOne = foldr (<|>) goNext
----------------------------------------------------------------
{-| Exception to control 'Alternative' 'IO'.
-}
data AltIOgoNext = AltIOgoNext deriving (Show, Typeable)
instance Exception AltIOgoNext