multi-except - succeed, or return one or more errors
-- in your cabal file
-- Add the main package (only depends on base!)
, multi-except
-- For the Alt instance (depends on semigroupoids)
, multi-except:semigroupoid-instances
{-# 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)
-- errors: Errors ["no monad instance", "i am scared"]
The use of ApplicativeDo
is significant and necessary for using
MultiExcept
with do notation.
MultiExcept
is not a Monad
, only an Applicative
, so a few constraints
apply, such as not being able to determine the structure of the rest of the
computation based on a previously do-bound value. If the previous sentence was
confusing, then you might want to consider using a writer monad instead.
To compose with other applicative effects, you can use
Data.Functor.Compose
.