multi-except 1.0.0 → 2.0.0
raw patch · 4 files changed
+65/−15 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Applicative.MultiExcept: runMultiExcept :: MultiExcept err a -> Either (NonEmptyDList err) a
+ Control.Applicative.MultiExcept: runMultiExcept :: MultiExcept err a -> Either (NonEmpty err) a
Files
- CHANGELOG.md +4/−0
- README.md +1/−0
- multi-except.cabal +2/−2
- multi-except/Control/Applicative/MultiExcept.hs +58/−13
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for multi-except +## Unreleased++* Actually give the user a useful collection of errors+ ## 1.0.0 -- 2024-01-03 * Split into two libraries, `multi-except`, and `multi-except:semigroupoid-instances`
README.md view
@@ -2,6 +2,7 @@ [](https://hackage.haskell.org/package/multi-except) [](https://github.com/414owen/multi-except/actions)+[](https://github.com/414owen/multi-except/blob/master/LICENSE) multi-except - succeed, or return one or more errors
multi-except.cabal view
@@ -1,9 +1,9 @@ cabal-version: 3.0 name: multi-except-version: 1.0.0+version: 2.0.0 synopsis: Multiple Exceptions-description: Report multiple errors, or a single correct value.+description: Succeed, or return one or more errors. license: MIT license-file: LICENSE author: Owen Shepherd
multi-except/Control/Applicative/MultiExcept.hs view
@@ -1,11 +1,31 @@-{-|-Module : Control.Applicative.MultiExcept-Copyright : (c) Owen Shepherd, 2021-License : MIT-Maintainer : owen@owen.cafe-Stability : stable-Portability : portable--}+-- |+-- Module : Control.Applicative.MultiExcept+-- Copyright : (c) Owen Shepherd, 2021+-- License : MIT+-- Maintainer : owen@owen.cafe+-- Stability : stable+-- Portability : portable+--+--+-- Usage:+--+-- Errors are accumulated through 'Applicative' sequencing.+-- The recommended way to use 'MultiExcept' is with `ApplicativeDo`:+--+-- @+-- {-# LANGUAGE ApplicativeDo #-}+--+-- import Control.Applicative.MultiExcept+--+-- errors :: MultiExcept String (Int, Int, Int)+-- errors = do+-- a <- throwError "no monad instance"+-- b <- pure 12+-- c <- throwError "i am scared"+-- pure (a, b, c)+-- @+--+-- {-# LANGUAGE CPP #-} {-# LANGUAGE NoImplicitPrelude #-}@@ -24,7 +44,7 @@ , mapMultiExcept ) where -import Prelude (Eq(..), Ord(..), Either(..), (.), ($), id, Show(..), (++))+import Prelude (Eq(..), Ord(..), Either(..), (.), ($), id, Show(..), (++), uncurry) import Control.Applicative (Applicative(..)) #if MIN_VERSION_base(4,8,0)@@ -80,11 +100,22 @@ | Errors !(NonEmptyDList err) deriving (Eq, Ord, Show) +#if MIN_VERSION_base(4,9,0)+ -- | Run the computation.-runMultiExcept :: MultiExcept err a -> Either (NonEmptyDList err) a-runMultiExcept (Errors errs) = Left errs+runMultiExcept :: MultiExcept err a -> Either (NonEmpty err) a+runMultiExcept (Errors errs) = Left $ uncurry (:|) $ runNonEmptyDList errs runMultiExcept (Success a) = Right a +#else++-- | Run the computation.+runMultiExcept :: MultiExcept err a -> Either (err, [err]) a+runMultiExcept (Errors errs) = Left $ runNonEmptyDList errs+runMultiExcept (Success a) = Right a++#endif+ -- | Throw a single error. throwError :: forall a err. err -> MultiExcept err a throwError = Errors . nedlSingleton@@ -129,8 +160,9 @@ #endif -- | Join nested 'MultiExcept's with the same error type.--- Note that this doesn't imply a __useful__ 'Monad' instance.--- The instance defined in terms of join discards errors on the RHS of '>>='.+-- Note that this doesn't imply a __useful__ 'Control.Monad.Monad' instance.+-- The instance defined in terms of join discards errors on the RHS of 'Control.Monad.>>=',+-- when the LHS is an error value. join :: MultiExcept err (MultiExcept err a) -> MultiExcept err a join (Success a) = a join (Errors a) = Errors a@@ -139,6 +171,7 @@ fmap f (Success a) = Success $ f a fmap _ (Errors errs) = Errors errs +-- | A non-overloaded `bimap` mapMultiExcept:: (err -> err') -> (a -> a') -> MultiExcept err a -> MultiExcept err' a' mapMultiExcept _ fa (Success a) = Success $ fa a mapMultiExcept ferr _ (Errors err) = Errors $ fmap ferr err@@ -161,6 +194,18 @@ Errors l <*> _ = Errors l _ <*> Errors l = Errors l +-- | Return the first success, or all of the combined errors.+--+-- ==== __Examples__+--+-- >>> pure 1 `or` throwError 3+-- Success 1+--+-- >>> throwError 2 `or` pure 1+-- Success 1+--+-- >>> throwError 2 `or` throwError 3+-- Errors [2, 3] or :: MultiExcept err a -> MultiExcept err a -> MultiExcept err a Success a `or` _ = Success a _ `or` Success a = Success a