diff --git a/src/HaskellWorks/Error.hs b/src/HaskellWorks/Error.hs index 2d2a4dc..48a9da3 100644 --- a/src/HaskellWorks/Error.hs +++ b/src/HaskellWorks/Error.hs @@ -1,28 +1,107 @@ module HaskellWorks.Error - ( onLeft, - onNothing, - onLeftM, + ( onNothing, onNothingM, + onLeft, + onLeftM, + onLeft_, + onLeftM_, + onMany, + onManyM, + onMany_, + onManyM_, ) where -import HaskellWorks.Prelude - -onLeft :: forall e a m. () - => Monad m - => (e -> m a) -> Either e a -> m a -onLeft f = either f pure +import Control.Applicative +import Control.Monad +import Data.Either +import Data.Function +import Data.List.NonEmpty +import Data.Maybe +-- | Handle the case where a value is 'Nothing'. onNothing :: forall a m. () => Monad m - => m a -> Maybe a -> m a + => m a + -> Maybe a + -> m a onNothing h = maybe h return +-- | Handle the case where an effectful function returns 'Nothing'. +onNothingM :: forall a m. () + => Monad m + => m a + -> m (Maybe a) + -> m a +onNothingM h f = onNothing h =<< f + +-- | Handle the case where a value is 'Left'. +onLeft :: forall e a m. () + => Monad m + => (e -> m a) + -> Either e a + -> m a +onLeft f = either f pure + +-- | Handle the case where an effectful function returns 'Left'. onLeftM :: forall e a m. () => Monad m - => (e -> m a) -> m (Either e a) -> m a + => (e -> m a) + -> m (Either e a) + -> m a onLeftM f action = onLeft f =<< action -onNothingM :: forall a m. () +-- | Handle the case where a value is 'Left'. +onLeft_ :: forall e a m. () => Monad m - => m a -> m (Maybe a) -> m a -onNothingM h f = onNothing h =<< f + => m a + -> Either e a + -> m a +onLeft_ f = either (const f) pure + +-- | Handle the case where an effectful function returns 'Left'. +onLeftM_ :: forall e a m. () + => Monad m + => m a + -> m (Either e a) + -> m a +onLeftM_ f action = onLeft_ f =<< action + +-- | Handle the case where a list with many (more than one) elements. +onMany :: forall a m.() + => Monad m + => (NonEmpty a -> m (Maybe a)) + -> [a] + -> m (Maybe a) +onMany h as = case as of + [] -> pure Nothing + [x] -> pure (Just x) + (x : xs) -> h (x :| xs) + +-- | Handle the case where an effectul function returns a list with many (more than one) elements. +onManyM :: forall a m.() + => Monad m + => (NonEmpty a -> m (Maybe a)) + -> m [a] + -> m (Maybe a) +onManyM h f = + f >>= onMany h + +-- | Handle the case where a list with many (more than one) elements. +onMany_ :: forall a m.() + => Monad m + => m (Maybe a) + -> [a] + -> m (Maybe a) +onMany_ h as = case as of + [] -> pure Nothing + [x] -> pure (Just x) + _ -> h + +-- | Handle the case where an effectul function returns a list with many (more than one) elements. +onManyM_ :: forall a m.() + => Monad m + => m (Maybe a) + -> m [a] + -> m (Maybe a) +onManyM_ h f = + f >>= onMany_ h diff --git a/src/HaskellWorks/Prelude.hs b/src/HaskellWorks/Prelude.hs index 2603990..1fcd261 100644 --- a/src/HaskellWorks/Prelude.hs +++ b/src/HaskellWorks/Prelude.hs @@ -165,6 +165,17 @@ module HaskellWorks.Prelude IOException, IOError, SomeException(..), + + onNothing, + onNothingM, + onLeft, + onLeftM, + onLeft_, + onLeftM_, + onMany, + onManyM, + onMany_, + onManyM_, ) where import Control.Applicative @@ -196,6 +207,7 @@ import GHC.Generics import GHC.Num import GHC.Real import GHC.Stack +import HaskellWorks.Error import Prelude import System.FilePath