{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} {- | Copyright: (c) 2016 Stephen Diehl (c) 2016-2018 Serokell (c) 2018-2020 Kowainik SPDX-License-Identifier: MIT Maintainer: Kowainik <xrom.xkov@gmail.com> Stability: Stable Portability: Portable Utilities to work with 'Relude.Either' data type. -} module Relude.Monad.Either ( -- * Combinators fromLeft , fromRight , maybeToLeft , maybeToRight , leftToMaybe , rightToMaybe , whenLeft , whenLeft_ -- * Monadic combinators , whenLeftM , whenLeftM_ , whenRight , whenRight_ , whenRightM , whenRightM_ ) where import Control.Applicative (Applicative) import Control.Monad (Monad (..)) import Data.Function (const) import Data.Maybe (Maybe (..), maybe) import Relude.Applicative (pure) import Relude.Function ((.)) import Relude.Monad.Reexport (Either (..), MonadFail (..), either) import Relude.String.Reexport (IsString (..), String) #if MIN_VERSION_base(4,10,0) import Data.Either (fromLeft, fromRight) #else -- | Extracts value from 'Left' or return given default value. -- -- >>> fromLeft 0 (Left 3) -- 3 -- >>> fromLeft 0 (Right 5) -- 0 fromLeft :: a -> Either a b -> a fromLeft _ (Left a) = a fromLeft a (Right _) = a -- | Extracts value from 'Right' or return given default value. -- -- >>> fromRight 0 (Left 3) -- 0 -- >>> fromRight 0 (Right 5) -- 5 fromRight :: b -> Either a b -> b fromRight b (Left _) = b fromRight _ (Right b) = b #endif -- $setup -- >>> import Relude {- | For convenient work with 'MonadFail'. @since 0.1.0 -} instance IsString str => MonadFail (Either str) where fail :: String -> Either str a fail = Left . fromString {-# INLINE fail #-} {- | Maps left part of 'Either' to 'Maybe'. >>> leftToMaybe (Left True) Just True >>> leftToMaybe (Right "aba") Nothing -} leftToMaybe :: Either l r -> Maybe l leftToMaybe = either Just (const Nothing) {-# INLINE leftToMaybe #-} {- | Maps right part of 'Either' to 'Maybe'. >>> rightToMaybe (Left True) Nothing >>> rightToMaybe (Right "aba") Just "aba" -} rightToMaybe :: Either l r -> Maybe r rightToMaybe = either (const Nothing) Just {-# INLINE rightToMaybe #-} {- | Maps 'Maybe' to 'Either' wrapping default value into 'Left'. >>> maybeToRight True (Just "aba") Right "aba" >>> maybeToRight True Nothing Left True -} maybeToRight :: l -> Maybe r -> Either l r maybeToRight l = maybe (Left l) Right {-# INLINE maybeToRight #-} {- | Maps 'Maybe' to 'Either' wrapping default value into 'Right'. >>> maybeToLeft True (Just "aba") Left "aba" >>> maybeToLeft True Nothing Right True -} maybeToLeft :: r -> Maybe l -> Either l r maybeToLeft r = maybe (Right r) Left {-# INLINE maybeToLeft #-} {- | Applies given action to 'Either' content if 'Left' is given and returns the result. In case of 'Right' the default value will be returned. >>> whenLeft "bar" (Left 42) (\a -> "success!" <$ print a) 42 "success!" >>> whenLeft "bar" (Right 42) (\a -> "success!" <$ print a) "bar" -} whenLeft :: Applicative f => a -> Either l r -> (l -> f a) -> f a whenLeft _ (Left l) f = f l whenLeft a (Right _) _ = pure a {-# INLINE whenLeft #-} {- | Applies given action to 'Either' content if 'Left' is given. >>> whenLeft_ (Right 42) putTextLn >>> whenLeft_ (Left "foo") putTextLn foo -} whenLeft_ :: Applicative f => Either l r -> (l -> f ()) -> f () whenLeft_ = whenLeft () {-# INLINE whenLeft_ #-} {- | Monadic version of 'whenLeft'. >>> whenLeftM "bar" (pure $ Left 42) (\a -> "success!" <$ print a) 42 "success!" >>> whenLeftM "bar" (pure $ Right 42) (\a -> "success!" <$ print a) "bar" -} whenLeftM :: Monad m => a -> m (Either l r) -> (l -> m a) -> m a whenLeftM a me f = me >>= \e -> whenLeft a e f {-# INLINE whenLeftM #-} {- | Monadic version of 'whenLeft_'. >>> whenLeftM_ (pure $ Right 42) putTextLn >>> whenLeftM_ (pure $ Left "foo") putTextLn foo -} whenLeftM_ :: Monad m => m (Either l r) -> (l -> m ()) -> m () whenLeftM_ me f = me >>= \e -> whenLeft_ e f {-# INLINE whenLeftM_ #-} {- | Applies given action to 'Either' content if 'Right' is given and returns the result. In case of 'Left' the default value will be returned. >>> whenRight "bar" (Left "foo") (\a -> "success!" <$ print a) "bar" >>> whenRight "bar" (Right 42) (\a -> "success!" <$ print a) 42 "success!" -} whenRight :: Applicative f => a -> Either l r -> (r -> f a) -> f a whenRight a (Left _) _ = pure a whenRight _ (Right r) f = f r {-# INLINE whenRight #-} {- | Applies given action to 'Either' content if 'Right' is given. >>> whenRight_ (Left "foo") print >>> whenRight_ (Right 42) print 42 -} whenRight_ :: Applicative f => Either l r -> (r -> f ()) -> f () whenRight_ = whenRight () {-# INLINE whenRight_ #-} {- | Monadic version of 'whenRight'. >>> whenRightM "bar" (pure $ Left "foo") (\a -> "success!" <$ print a) "bar" >>> whenRightM "bar" (pure $ Right 42) (\a -> "success!" <$ print a) 42 "success!" -} whenRightM :: Monad m => a -> m (Either l r) -> (r -> m a) -> m a whenRightM a me f = me >>= \e -> whenRight a e f {-# INLINE whenRightM #-} {- | Monadic version of 'whenRight_'. >>> whenRightM_ (pure $ Left "foo") print >>> whenRightM_ (pure $ Right 42) print 42 -} whenRightM_ :: Monad m => m (Either l r) -> (r -> m ()) -> m () whenRightM_ me f = me >>= \e -> whenRight_ e f {-# INLINE whenRightM_ #-}