-- | Extra functions for dealing with Either.

module Data.Either.Extra where

-- | A map for Either values.
mapEither :: (a -> b1) -> (b -> b2) -> Either a b -> Either b1 b2
mapEither l r = either (Left . l) (Right . r)

-- | Maybe get the left side of an Either.
leftToMaybe :: Either a b -> Maybe a
leftToMaybe = either Just (const Nothing)

-- | Maybe get the right side of an Either.
rightToMaybe :: Either a b -> Maybe b
rightToMaybe = either (const Nothing) Just

-- | Is a value Left?
isLeft :: Either a b -> Bool
isLeft (Left _) = True
isLeft (Right _) = False

-- | Is a value Right?
isRight :: Either a b -> Bool
isRight (Left _) = False
isRight (Right _) = True

-- | Extract the left value or a default.
fromLeft :: a -> Either a b -> a
fromLeft _ (Left x) = x
fromLeft x _ = x

-- | Extract the right value or a default.
fromRight :: b -> Either a b -> b
fromRight _ (Right x) = x
fromRight x _ = x

-- | When a value is Right, do something with it, monadically.
whenRight :: Monad m => Either a b -> (b -> m c) -> m ()
whenRight (Right x) m = m x >> return ()
whenRight _         _ = return ()

-- | When a value is Left, do something with it, monadically.
whenLeft :: Monad m => Either a b -> (a -> m c) -> m ()
whenLeft (Left x) m = m x >> return ()
whenLeft _         _ = return ()