{-# LANGUAGE DeriveAnyClass       #-}
{-# LANGUAGE DeriveDataTypeable   #-}
{-# language DerivingStrategies #-}
{-# language DeriveGeneric #-}
{-# language LambdaCase #-}

{- |
Copyright:  (c) 2014 Chris Allen
            (c) 2014 Edward Kmett
            (c) 2018-2023 Kowainik
            (c) 2023 Marco Zocca, UnfoldML
SPDX-License-Identifier: BSD-3-Clause
Maintainer:  oss@unfoldml.com
Stability:   Stable
Portability: Portable

Lightweight pure data validation based on 'Applicative' functors.

'Validation' allows to accumulate all errors instead of
short-circuting on the first error so you can display all possible
errors at once.

Common use-cases include:

1. Validating each input of a form with multiple inputs.
2. Performing multiple validations of a single value.

'Validation' provides __modular__ and __composable__ interface which
means that you can implement validations for different pieces of your
data independently, and then combine smaller parts into the validation
of a bigger type. The below table illustrates main ways to combine two
'Validation's:

+---------------+-------------+---------------------------+---------------------------+---------------------------+---------------------------+
|   Typeclass   | Operation ○ | 'Failure' e ○ 'Failure' d | 'Success' a ○ 'Success' b | 'Failure' e ○ 'Success' a | 'Success' a ○ 'Failure' e |
+===============+=============+===========================+===========================+===========================+===========================+
| 'Semigroup'   | '<>'        | 'Failure' (e '<>' d)      | 'Success' (a '<>' b)      | 'Failure' e               | 'Failure' e               |
+---------------+-------------+---------------------------+---------------------------+---------------------------+---------------------------+
| 'Applicative' | '<*>'       | 'Failure' (e '<>' d)      | 'Success' (a b)           | 'Failure' e               | 'Failure' e               |
+---------------+-------------+---------------------------+---------------------------+---------------------------+---------------------------+
| 'Alternative' | '<|>'       | 'Failure' (e '<>' d)      | 'Success' a               | 'Success' a               | 'Success' a               |
+---------------+-------------+---------------------------+---------------------------+---------------------------+---------------------------+


In other words, instances of different standard typeclasses provide
various semantics which can be useful in different use-cases:

1. 'Semigroup': accumulate both 'Failure' and 'Success' with '<>'.
2. 'Monoid': 'Success' that stores 'mempty'.
3. 'Functor': change the type inside 'Success'.
4. 'Bifunctor': change both 'Failure' and 'Success'.
5. 'Applicative': apply function to values inside 'Success' and accumulate
   errors inside 'Failure'.
6. 'Alternative': return the first 'Success' or accumulate all errors
   inside 'Failure'.
-}

module Validation.Micro (
  -- * Type
         Validation (..)

         -- * How to use
         -- $use

         -- * Interface functions
       , isFailure
       , isSuccess
       , validation
       , failures
       , successes
       , partitionValidations
       , fromFailure
       , fromSuccess
       , bindValidation

         -- ** 'NonEmpty' combinators
         -- $nonEmptyCombinators
       , failure
       , failureIf
       , failureUnless

         -- ** 'Either' conversion
         -- $either
       , validationToEither
       , eitherToValidation

         -- * Combinators
       , validateAll

      -- * When* functions
    , whenSuccess
    , whenFailure
    , whenSuccess_
    , whenFailure_
    , whenSuccessM
    , whenFailureM
    , whenSuccessM_
    , whenFailureM_

      -- * 'Maybe' conversion
    , failureToMaybe
    , successToMaybe
    , maybeToFailure
    , maybeToSuccess
  ) where

import Control.Applicative (Alternative (..), Applicative (..))
import Data.Bifoldable (Bifoldable (..))
import Data.Bifunctor (Bifunctor (..))
import Data.Bitraversable (Bitraversable (..))
import Data.Data (Data)
import Control.DeepSeq (NFData, NFData1, NFData2(..))
import Data.Foldable (Foldable (..))
import Data.List.NonEmpty (NonEmpty (..))

import GHC.Generics (Generic(..), Generic1(..))

{- | 'Validation' is a sum type for storing either all
validation failures or validation success. Unlike 'Either', which
returns only the first error, 'Validation' accumulates all errors
using the 'Semigroup' typeclass.

Usually type variables in @'Validation' e a@ are used as follows:

* @e@: is a list or set of failure messages or values of some error data type.
* @a@: is some domain type denoting successful validation result.

Some typical use-cases:

* @'Validation' ['String'] User@

    * Either list of 'String' error messages or a validated value of a
      custom @User@ type.

* @'Validation' ('NonEmpty' UserValidationError) User@

    * Similar to previous example, but list of failures guaranteed to
      be non-empty in case of validation failure, and it stores values
      of some custom error type.
-}
data Validation e a
    = Failure e
    -- ^ Validation failure. The @e@ type is supposed to implement the 'Semigroup' instance.
    | Success a
    -- ^ Successful validation result of type @a@.
    deriving stock (Validation e a -> Validation e a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall e a.
(Eq e, Eq a) =>
Validation e a -> Validation e a -> Bool
/= :: Validation e a -> Validation e a -> Bool
$c/= :: forall e a.
(Eq e, Eq a) =>
Validation e a -> Validation e a -> Bool
== :: Validation e a -> Validation e a -> Bool
$c== :: forall e a.
(Eq e, Eq a) =>
Validation e a -> Validation e a -> Bool
Eq, Validation e a -> Validation e a -> Bool
Validation e a -> Validation e a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {e} {a}. (Ord e, Ord a) => Eq (Validation e a)
forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Bool
forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Ordering
forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Validation e a
min :: Validation e a -> Validation e a -> Validation e a
$cmin :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Validation e a
max :: Validation e a -> Validation e a -> Validation e a
$cmax :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Validation e a
>= :: Validation e a -> Validation e a -> Bool
$c>= :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Bool
> :: Validation e a -> Validation e a -> Bool
$c> :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Bool
<= :: Validation e a -> Validation e a -> Bool
$c<= :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Bool
< :: Validation e a -> Validation e a -> Bool
$c< :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Bool
compare :: Validation e a -> Validation e a -> Ordering
$ccompare :: forall e a.
(Ord e, Ord a) =>
Validation e a -> Validation e a -> Ordering
Ord, Int -> Validation e a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall e a. (Show e, Show a) => Int -> Validation e a -> ShowS
forall e a. (Show e, Show a) => [Validation e a] -> ShowS
forall e a. (Show e, Show a) => Validation e a -> String
showList :: [Validation e a] -> ShowS
$cshowList :: forall e a. (Show e, Show a) => [Validation e a] -> ShowS
show :: Validation e a -> String
$cshow :: forall e a. (Show e, Show a) => Validation e a -> String
showsPrec :: Int -> Validation e a -> ShowS
$cshowsPrec :: forall e a. (Show e, Show a) => Int -> Validation e a -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall e a x. Rep (Validation e a) x -> Validation e a
forall e a x. Validation e a -> Rep (Validation e a) x
$cto :: forall e a x. Rep (Validation e a) x -> Validation e a
$cfrom :: forall e a x. Validation e a -> Rep (Validation e a) x
Generic, forall e a. Rep1 (Validation e) a -> Validation e a
forall e a. Validation e a -> Rep1 (Validation e) a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
$cto1 :: forall e a. Rep1 (Validation e) a -> Validation e a
$cfrom1 :: forall e a. Validation e a -> Rep1 (Validation e) a
Generic1, Validation e a -> DataType
Validation e a -> Constr
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall {e} {a}. (Data e, Data a) => Typeable (Validation e a)
forall e a. (Data e, Data a) => Validation e a -> DataType
forall e a. (Data e, Data a) => Validation e a -> Constr
forall e a.
(Data e, Data a) =>
(forall b. Data b => b -> b) -> Validation e a -> Validation e a
forall e a u.
(Data e, Data a) =>
Int -> (forall d. Data d => d -> u) -> Validation e a -> u
forall e a u.
(Data e, Data a) =>
(forall d. Data d => d -> u) -> Validation e a -> [u]
forall e a r r'.
(Data e, Data a) =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Validation e a -> r
forall e a r r'.
(Data e, Data a) =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Validation e a -> r
forall e a (m :: * -> *).
(Data e, Data a, Monad m) =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
forall e a (m :: * -> *).
(Data e, Data a, MonadPlus m) =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
forall e a (c :: * -> *).
(Data e, Data a) =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Validation e a)
forall e a (c :: * -> *).
(Data e, Data a) =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Validation e a -> c (Validation e a)
forall e a (t :: * -> *) (c :: * -> *).
(Data e, Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Validation e a))
forall e a (t :: * -> * -> *) (c :: * -> *).
(Data e, Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Validation e a))
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Validation e a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Validation e a -> c (Validation e a)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Validation e a))
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
$cgmapMo :: forall e a (m :: * -> *).
(Data e, Data a, MonadPlus m) =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
$cgmapMp :: forall e a (m :: * -> *).
(Data e, Data a, MonadPlus m) =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
$cgmapM :: forall e a (m :: * -> *).
(Data e, Data a, Monad m) =>
(forall d. Data d => d -> m d)
-> Validation e a -> m (Validation e a)
gmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> Validation e a -> u
$cgmapQi :: forall e a u.
(Data e, Data a) =>
Int -> (forall d. Data d => d -> u) -> Validation e a -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Validation e a -> [u]
$cgmapQ :: forall e a u.
(Data e, Data a) =>
(forall d. Data d => d -> u) -> Validation e a -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Validation e a -> r
$cgmapQr :: forall e a r r'.
(Data e, Data a) =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Validation e a -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Validation e a -> r
$cgmapQl :: forall e a r r'.
(Data e, Data a) =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Validation e a -> r
gmapT :: (forall b. Data b => b -> b) -> Validation e a -> Validation e a
$cgmapT :: forall e a.
(Data e, Data a) =>
(forall b. Data b => b -> b) -> Validation e a -> Validation e a
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Validation e a))
$cdataCast2 :: forall e a (t :: * -> * -> *) (c :: * -> *).
(Data e, Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Validation e a))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Validation e a))
$cdataCast1 :: forall e a (t :: * -> *) (c :: * -> *).
(Data e, Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Validation e a))
dataTypeOf :: Validation e a -> DataType
$cdataTypeOf :: forall e a. (Data e, Data a) => Validation e a -> DataType
toConstr :: Validation e a -> Constr
$ctoConstr :: forall e a. (Data e, Data a) => Validation e a -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Validation e a)
$cgunfold :: forall e a (c :: * -> *).
(Data e, Data a) =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Validation e a)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Validation e a -> c (Validation e a)
$cgfoldl :: forall e a (c :: * -> *).
(Data e, Data a) =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Validation e a -> c (Validation e a)
Data)
    deriving anyclass (forall a. (a -> ()) -> NFData a
forall e a. (NFData e, NFData a) => Validation e a -> ()
rnf :: Validation e a -> ()
$crnf :: forall e a. (NFData e, NFData a) => Validation e a -> ()
NFData, forall e a. NFData e => (a -> ()) -> Validation e a -> ()
forall (f :: * -> *).
(forall a. (a -> ()) -> f a -> ()) -> NFData1 f
liftRnf :: forall a. (a -> ()) -> Validation e a -> ()
$cliftRnf :: forall e a. NFData e => (a -> ()) -> Validation e a -> ()
NFData1)

{- | Allows changing the value inside 'Success' with a given function.

__Examples__

>>> fmap (+1) (Success 9)
Success 10
>>> fmap (+1) (Failure ["wrong"])
Failure ["wrong"]
-}
instance Functor (Validation e) where
    -- fmap :: (a -> b) -> Validation e a -> Validation e b
    fmap :: forall a b. (a -> b) -> Validation e a -> Validation e b
fmap a -> b
_ (Failure e
e) = forall e a. e -> Validation e a
Failure e
e
    fmap a -> b
f (Success a
a) = forall e a. a -> Validation e a
Success (a -> b
f a
a)
    {-# INLINE fmap #-}

    -- (<$) :: a -> Validation e b -> Validation e a
    a
x <$ :: forall a b. a -> Validation e b -> Validation e a
<$ Success b
_ = forall e a. a -> Validation e a
Success a
x
    a
_ <$ Failure e
e = forall e a. e -> Validation e a
Failure e
e
    {-# INLINE (<$) #-}


{- | 'Semigroup' allows merging multiple 'Validation's into single one
by combining values inside both 'Failure' and 'Success'. The '<>'
operator merges two 'Validation's following the below rules:

1. If both values are 'Failure's, returns a new 'Failure' with
accumulated errors.
2. If both values are 'Success'ful, returns a new 'Success' with
combined success using 'Semigroup' for values inside 'Success'.
3. If one value is 'Failure' and another one is 'Success', then
'Failure' is returned.

__Examples__

>>> success1 = Success [9] :: Validation [String] [Int]
>>> success2 = Success [15] :: Validation [String] [Int]
>>> failure1 = Failure ["WRONG"] :: Validation [String] [Int]
>>> failure2 = Failure ["FAIL"]  :: Validation [String] [Int]

>>> success1 <> success2
Success [9,15]
>>> failure1 <> failure2
Failure ["WRONG","FAIL"]
>>> success1 <> failure1
Failure ["WRONG"]
>>> failure2 <> success1 <> success2 <> failure1
Failure ["FAIL","WRONG"]
-}
instance (Semigroup e, Semigroup a) => Semigroup (Validation e a) where
    -- (<>) :: Validation e a -> Validation e a -> Validation e a
    <> :: Validation e a -> Validation e a -> Validation e a
(<>) = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>)
    {-# INLINE (<>) #-}

{- | @'mempty' :: 'Validation' e a@ is @Success@ which stores
@'mempty' :: a@ to be consistent with the 'Semigroup' instance.

__Examples__

>>> mempty :: Validation String [Bool]
Success []
-}
instance (Semigroup e, Monoid a) => Monoid (Validation e a) where
    mempty :: Validation e a
mempty = forall e a. a -> Validation e a
Success forall a. Monoid a => a
mempty
    {-# INLINE mempty #-}

    mappend :: Validation e a -> Validation e a -> Validation e a
mappend = forall a. Semigroup a => a -> a -> a
(<>)
    {-# INLINE mappend #-}



{- | This instance is the most important instance for the 'Validation' data
type. It's responsible for the many implementations. And it allows to accumulate
errors while performing validation or combining the results in the applicative
style.

__Examples__

>>> success1 = Success 9 :: Validation [String] Int
>>> success2 = Success 15 :: Validation [String] Int
>>> successF = Success (* 2) :: Validation [String] (Int -> Int)
>>> failure1 = Failure ["WRONG"] :: Validation [String] Int
>>> failure2 = Failure ["FAIL"]  :: Validation [String] Int

>>> successF <*> success1
Success 18
>>> successF <*> failure1
Failure ["WRONG"]
>>> (+) <$> success1 <*> success2
Success 24
>>> (+) <$> failure1 <*> failure2
Failure ["WRONG","FAIL"]
>>> liftA2 (+) success1 failure1
Failure ["WRONG"]
>>> liftA3 (,,) failure1 success1 failure2
Failure ["WRONG","FAIL"]

Implementations of all functions are lazy and they correctly work if some
arguments are not fully evaluated.

>>> failure1 *> failure2
Failure ["WRONG","FAIL"]
>>> isFailure $ failure1 *> failure2
True
>>> epicFail = error "Impossible validation" :: Validation [String] Int
>>> isFailure $ failure1 *> epicFail
True
-}
instance Semigroup e => Applicative (Validation e) where
    -- pure :: a -> Validation e a
    pure :: forall a. a -> Validation e a
pure = forall e a. a -> Validation e a
Success
    {-# INLINE pure #-}

    Failure e
e1 <*> :: forall a b.
Validation e (a -> b) -> Validation e a -> Validation e b
<*> Validation e a
b = forall e a. e -> Validation e a
Failure forall a b. (a -> b) -> a -> b
$ case Validation e a
b of
        Failure e
e2 -> e
e1 forall a. Semigroup a => a -> a -> a
<> e
e2
        Success a
_  -> e
e1
    Success a -> b
_ <*> Failure e
e = forall e a. e -> Validation e a
Failure e
e
    Success a -> b
f <*> Success a
a = forall e a. a -> Validation e a
Success (a -> b
f a
a)
    {-# INLINE (<*>) #-}

    Failure e
e1 *> :: forall a b. Validation e a -> Validation e b -> Validation e b
*> Validation e b
b = forall e a. e -> Validation e a
Failure forall a b. (a -> b) -> a -> b
$ case Validation e b
b of
        Failure e
e2 -> e
e1 forall a. Semigroup a => a -> a -> a
<> e
e2
        Success b
_  -> e
e1
    Success a
_ *> Failure e
e = forall e a. e -> Validation e a
Failure e
e
    Success a
_ *> Success b
b = forall e a. a -> Validation e a
Success b
b
    {-# INLINE (*>) #-}

    Failure e
e1 <* :: forall a b. Validation e a -> Validation e b -> Validation e a
<* Validation e b
b = forall e a. e -> Validation e a
Failure forall a b. (a -> b) -> a -> b
$ case Validation e b
b of
        Failure e
e2 -> e
e1 forall a. Semigroup a => a -> a -> a
<> e
e2
        Success b
_  -> e
e1
    Success a
_ <* Failure e
e = forall e a. e -> Validation e a
Failure e
e
    Success a
a <* Success b
_ = forall e a. a -> Validation e a
Success a
a
    {-# INLINE (<*) #-}

    liftA2 :: forall a b c.
(a -> b -> c) -> Validation e a -> Validation e b -> Validation e c
liftA2 a -> b -> c
_ (Failure e
e1) Validation e b
b = forall e a. e -> Validation e a
Failure forall a b. (a -> b) -> a -> b
$ case Validation e b
b of
        Failure e
e2 -> e
e1 forall a. Semigroup a => a -> a -> a
<> e
e2
        Success b
_  -> e
e1
    liftA2 a -> b -> c
_ (Success a
_) (Failure e
e) = forall e a. e -> Validation e a
Failure e
e
    liftA2 a -> b -> c
f (Success a
a) (Success b
b) = forall e a. a -> Validation e a
Success (a -> b -> c
f a
a b
b)
    {-# INLINE liftA2 #-}

-- | NB Validation is not a monad though
bindValidation :: Validation e a -> (a -> Validation e b) -> Validation e b
bindValidation :: forall e a b.
Validation e a -> (a -> Validation e b) -> Validation e b
bindValidation Validation e a
v a -> Validation e b
f = case Validation e a
v of
  Failure e
e -> forall e a. e -> Validation e a
Failure e
e
  Success a
a -> a -> Validation e b
f a
a


{- | This instance implements the behaviour when the first 'Success'
is returned. Otherwise all 'Failure's are combined.

__Examples__

>>> success1 = Success [9] :: Validation [String] [Int]
>>> success2 = Success [15] :: Validation [String] [Int]
>>> failure1 = Failure ["WRONG"] :: Validation [String] [Int]
>>> failure2 = Failure ["FAIL"]  :: Validation [String] [Int]

>>> success1 <|> success2
Success [9]
>>> failure1 <|> failure2
Failure ["WRONG","FAIL"]
>>> failure2 <|> success2
Success [15]
-}
instance (Monoid e) => Alternative (Validation e) where
    -- empty :: Validation e a
    empty :: forall a. Validation e a
empty = forall e a. e -> Validation e a
Failure forall a. Monoid a => a
mempty
    {-# INLINE empty #-}

    -- (<|>) :: Validation e a -> Validation e a -> Validation e a
    s :: Validation e a
s@Success{} <|> :: forall a. Validation e a -> Validation e a -> Validation e a
<|> Validation e a
_        = Validation e a
s
    Validation e a
_ <|> s :: Validation e a
s@Success{}        = Validation e a
s
    Failure e
e <|> Failure e
e' = forall e a. e -> Validation e a
Failure (e
e forall a. Semigroup a => a -> a -> a
<> e
e')
    {-# INLINE (<|>) #-}



{- | 'Foldable' for 'Validation' allows folding values inside 'Success'.

__Examples__

>>> fold (Success [16])
[16]
>>> fold (Failure "WRONG!" :: Validation String [Int])
[]
-}
instance Foldable (Validation e) where
    fold :: forall m. Monoid m => Validation e m -> m
fold = \case
        Failure e
_ -> forall a. Monoid a => a
mempty
        Success m
a -> m
a
    {-# INLINE fold #-}

    foldMap :: forall m a. Monoid m => (a -> m) -> Validation e a -> m
foldMap a -> m
f = \case
        Failure e
_ -> forall a. Monoid a => a
mempty
        Success a
a -> a -> m
f a
a
    {-# INLINE foldMap #-}

    foldr :: forall a b. (a -> b -> b) -> b -> Validation e a -> b
foldr a -> b -> b
f b
x = \case
        Failure e
_ -> b
x
        Success a
a -> a -> b -> b
f a
a b
x
    {-# INLINE foldr #-}

    foldr' :: forall a b. (a -> b -> b) -> b -> Validation e a -> b
foldr' = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
    {-# INLINE foldr' #-}

    foldl :: forall b a. (b -> a -> b) -> b -> Validation e a -> b
foldl b -> a -> b
f b
x = \case
        Failure e
_ -> b
x
        Success a
a -> b -> a -> b
f b
x a
a
    {-# INLINE foldl #-}

    foldl' :: forall b a. (b -> a -> b) -> b -> Validation e a -> b
foldl' = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl
    {-# INLINE foldl' #-}

    toList :: forall a. Validation e a -> [a]
toList = \case
        Failure e
_ -> []
        Success a
a -> [a
a]
    {-# INLINE toList #-}

    null :: forall a. Validation e a -> Bool
null = \case
        Failure e
_ -> Bool
True
        Success a
_ -> Bool
False
    {-# INLINE null #-}

    length :: forall a. Validation e a -> Int
length = \case
        Failure e
_ -> Int
0
        Success a
_ -> Int
1
    {-# INLINE length #-}

    elem :: forall a. Eq a => a -> Validation e a -> Bool
elem a
x = \case
        Failure e
_ -> Bool
False
        Success a
a -> a
x forall a. Eq a => a -> a -> Bool
== a
a
    {-# INLINE elem #-}

    sum :: forall a. Num a => Validation e a -> a
sum = \case
        Failure e
_ -> a
0
        Success a
a -> a
a
    {-# INLINE sum #-}

    product :: forall a. Num a => Validation e a -> a
product = \case
        Failure e
_ -> a
1
        Success a
a -> a
a
    {-# INLINE product #-}



{- | Traverse values inside 'Success' with some effectful computation.

__Examples__

>>> parseInt = readMaybe :: String -> Maybe Int
>>> traverse parseInt (Success "42")
Just (Success 42)
>>> traverse parseInt (Success "int")
Nothing
>>> traverse parseInt (Failure ["42"])
Just (Failure ["42"])
-}
instance Traversable (Validation e) where
    traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Validation e a -> f (Validation e b)
traverse a -> f b
f (Success a
a) = forall e a. a -> Validation e a
Success forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
a
    traverse a -> f b
_ (Failure e
e) = forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall e a. e -> Validation e a
Failure e
e)
    {-# INLINE traverse #-}

    sequenceA :: forall (f :: * -> *) a.
Applicative f =>
Validation e (f a) -> f (Validation e a)
sequenceA = \case
        Failure e
e -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall e a. e -> Validation e a
Failure e
e)
        Success f a
f -> forall e a. a -> Validation e a
Success forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f a
f
    {-# INLINE sequenceA #-}

{- | Similar to 'Functor' but allows mapping of values inside both
'Failure' and 'Success'.

__Examples__

>>> bimap length show (Success 50)
Success "50"
>>> bimap length show (Failure ["15", "9"])
Failure 2
-}
instance Bifunctor Validation where
    bimap :: forall a b c d.
(a -> b) -> (c -> d) -> Validation a c -> Validation b d
bimap a -> b
f c -> d
_ (Failure a
e) = forall e a. e -> Validation e a
Failure (a -> b
f a
e)
    bimap a -> b
_ c -> d
g (Success c
a) = forall e a. a -> Validation e a
Success (c -> d
g c
a)
    {-# INLINE bimap #-}

    first :: forall a b c. (a -> b) -> Validation a c -> Validation b c
first a -> b
f (Failure a
e) = forall e a. e -> Validation e a
Failure (a -> b
f a
e)
    first a -> b
_ (Success c
a) = forall e a. a -> Validation e a
Success c
a
    {-# INLINE first #-}

    second :: forall b c a. (b -> c) -> Validation a b -> Validation a c
second b -> c
_ (Failure a
e) = forall e a. e -> Validation e a
Failure a
e
    second b -> c
g (Success b
a) = forall e a. a -> Validation e a
Success (b -> c
g b
a)
    {-# INLINE second #-}




{- | Similar to 'Foldable' but allows folding both 'Failure' and
'Success' to the same monoidal value according to given functions.

__Examples__

>>> one x = [x]
>>> bifoldMap id (one . show) (Success 15)
["15"]
>>> bifoldMap id (one . show) (Failure ["Wrong", "Fail"])
["Wrong","Fail"]
-}
instance Bifoldable Validation where
    bifoldMap :: forall m a b.
Monoid m =>
(a -> m) -> (b -> m) -> Validation a b -> m
bifoldMap a -> m
f b -> m
_ (Failure a
e) = a -> m
f a
e
    bifoldMap a -> m
_ b -> m
g (Success b
a) = b -> m
g b
a
    {-# INLINE bifoldMap #-}

{- | Similar to 'Traversable' but traverses both 'Failure' and
'Success' with given effectful computations.

__Examples__

>>> parseInt = readMaybe :: String -> Maybe Int
>>> bitraverse listToMaybe parseInt (Success "42")
Just (Success 42)
>>> bitraverse listToMaybe parseInt (Success "int")
Nothing
>>> bitraverse listToMaybe parseInt (Failure [15])
Just (Failure 15)
>>> bitraverse listToMaybe parseInt (Failure [])
Nothing
-}
instance Bitraversable Validation where
    bitraverse :: forall (f :: * -> *) a c b d.
Applicative f =>
(a -> f c) -> (b -> f d) -> Validation a b -> f (Validation c d)
bitraverse a -> f c
f b -> f d
_ (Failure a
e) = forall e a. e -> Validation e a
Failure forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f c
f a
e
    bitraverse a -> f c
_ b -> f d
g (Success b
a) = forall e a. a -> Validation e a
Success forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> f d
g b
a
    {-# INLINE bitraverse #-}

instance NFData2 Validation where
    liftRnf2 :: forall a b. (a -> ()) -> (b -> ()) -> Validation a b -> ()
liftRnf2 a -> ()
f b -> ()
_s (Failure a
x) = a -> ()
f a
x
    liftRnf2 a -> ()
_f b -> ()
s (Success b
y) = b -> ()
s b
y




{- |
== Combinators

We are providing several functions for better integration with the 'Either'
related code in this section.
-}

{- | Transform a 'Validation' into an 'Either'.

>>> validationToEither (Success "whoop")
Right "whoop"

>>> validationToEither (Failure "nahh")
Left "nahh"
-}
validationToEither :: Validation e a -> Either e a
validationToEither :: forall e a. Validation e a -> Either e a
validationToEither = \case
    Failure e
e -> forall a b. a -> Either a b
Left e
e
    Success a
a -> forall a b. b -> Either a b
Right a
a
{-# INLINE validationToEither #-}

{- | Transform an 'Either' into a 'Validation'.

>>> eitherToValidation (Right "whoop")
Success "whoop"

>>> eitherToValidation (Left "nahh")
Failure "nahh"
-}
eitherToValidation :: Either e a -> Validation e a
eitherToValidation :: forall e a. Either e a -> Validation e a
eitherToValidation = \case
    Left e
e  -> forall e a. e -> Validation e a
Failure e
e
    Right a
a -> forall e a. a -> Validation e a
Success a
a
{-# INLINE eitherToValidation #-}



----------------------------------------------------------------------------
-- Interface
----------------------------------------------------------------------------

{- | Predicate on if the given 'Validation' is 'Failure'.

>>> isFailure (Failure 'e')
True
>>> isFailure (Success 'a')
False
-}
isFailure :: Validation e a -> Bool
isFailure :: forall e a. Validation e a -> Bool
isFailure = \case
    Failure e
_ -> Bool
True
    Success a
_ -> Bool
False

{- | Predicate on if the given 'Validation' is 'Success'.

>>> isSuccess (Success 'a')
True
>>> isSuccess (Failure 'e')
False
-}
isSuccess :: Validation e a -> Bool
isSuccess :: forall e a. Validation e a -> Bool
isSuccess = \case
    Success a
_ -> Bool
True
    Failure e
_ -> Bool
False

{- | Transforms the value of the given 'Validation' into @x@ using provided
functions that can transform 'Failure' and 'Success' value into the resulting
type respectively.

>>> let myValidation = validation (<> " world!") (show . (* 10))
>>> myValidation (Success 100)
"1000"
>>> myValidation (Failure "Hello")
"Hello world!"
-}
validation :: (e -> x) -> (a -> x) -> Validation e a -> x
validation :: forall e x a. (e -> x) -> (a -> x) -> Validation e a -> x
validation e -> x
fe a -> x
fa = \case
    Success a
a -> a -> x
fa a
a
    Failure e
e -> e -> x
fe e
e

{- | Filters out all 'Failure' values into the new list of @e@s from the given
list of 'Validation's.

Note that the order is preserved.

>>> failures [Failure "Hello", Success 1, Failure "world", Success 2, Failure "!" ]
["Hello","world","!"]
-}
failures :: [Validation e a] -> [e]
failures :: forall e a. [Validation e a] -> [e]
failures [Validation e a]
v = [e
e | Failure e
e <- [Validation e a]
v]
{-# INLINE failures #-}

{- | Filters out all 'Success' values into the new list of @a@s from the given
list of 'Validation's.

Note that the order is preserved.

>>> successes [Failure "Hello", Success 1, Failure "world", Success 2, Failure "!" ]
[1,2]
-}
successes :: [Validation e a] -> [a]
successes :: forall e a. [Validation e a] -> [a]
successes [Validation e a]
v = [a
a | Success a
a <- [Validation e a]
v]
{-# INLINE successes #-}

{- | Redistributes the given list of 'Validation's into two lists of @e@s and
@e@s, where the first list contains all values of 'Failure's and the second
one — 'Success'es correspondingly.

Note that the order is preserved.

>>> partitionValidations [Failure "Hello", Success 1, Failure "world", Success 2, Failure "!" ]
(["Hello","world","!"],[1,2])
-}
partitionValidations :: [Validation e a] -> ([e], [a])
partitionValidations :: forall e a. [Validation e a] -> ([e], [a])
partitionValidations = forall e a. [Validation e a] -> ([e], [a])
go
  where
    go :: [Validation e a] -> ([e], [a])
    go :: forall e a. [Validation e a] -> ([e], [a])
go []               = ([], [])
    go (Failure e
e:[Validation e a]
rest) = forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first  (e
eforall a. a -> [a] -> [a]
:) forall a b. (a -> b) -> a -> b
$ forall e a. [Validation e a] -> ([e], [a])
go [Validation e a]
rest
    go (Success a
a:[Validation e a]
rest) = forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (a
aforall a. a -> [a] -> [a]
:) forall a b. (a -> b) -> a -> b
$ forall e a. [Validation e a] -> ([e], [a])
go [Validation e a]
rest

{- | Returns the contents of a 'Failure'-value or a default value otherwise.

>>> fromFailure "default" (Failure "failure")
"failure"
>>> fromFailure "default" (Success 1)
"default"
-}
fromFailure :: e -> Validation e a -> e
fromFailure :: forall e a. e -> Validation e a -> e
fromFailure e
_ (Failure e
e) = e
e
fromFailure e
e Validation e a
_           = e
e

{- | Returns the contents of a 'Success'-value or a default value otherwise.

>>> fromSuccess 42 (Success 1)
1
>>> fromSuccess 42 (Failure "failure")
42
-}
fromSuccess :: a -> Validation e a -> a
fromSuccess :: forall a e. a -> Validation e a -> a
fromSuccess a
_ (Success a
a) = a
a
fromSuccess a
a Validation e a
_           = a
a

----------------------------------------------------------------------------
-- NonEmpty Combinators
----------------------------------------------------------------------------

{- $nonEmptyCombinators

When using 'Validation', we often work with the 'NonEmpty' list of errors, and
those lists will be concatenated later.

The following functions aim to help with writing more concise code.

For example, instead of (perfectly fine) code like:

>>> :{
validateNameVerbose :: String -> Validation (NonEmpty String) String
validateNameVerbose name
    | null name = Failure ("Empty Name" :| [])
    | otherwise = Success name
:}

one can write simply:

>>> :{
validateNameSimple :: String -> Validation (NonEmpty String) String
validateNameSimple name = name <$ failureIf (null name) "Empty Name"
:}

-}

{- | Create a 'Failure' of 'NonEmpty' list with a single given error.

>>> failure "I am a failure"
Failure ("I am a failure" :| [])
-}
failure :: e -> Validation (NonEmpty e) a
failure :: forall e a. e -> Validation (NonEmpty e) a
failure e
e = forall e a. e -> Validation e a
Failure (e
e forall a. a -> [a] -> NonEmpty a
:| [])
{-# INLINE failure #-}

{- | Returns a 'Failure' in case of the given predicate is 'True'.
Returns @'Success' ()@ otherwise.

>>> let shouldFail = (==) "I am a failure"
>>> failureIf (shouldFail "I am a failure") "I told you so"
Failure ("I told you so" :| [])
>>> failureIf (shouldFail "I am NOT a failure") "okay"
Success ()
-}
failureIf :: Bool -> e -> Validation (NonEmpty e) ()
failureIf :: forall e. Bool -> e -> Validation (NonEmpty e) ()
failureIf Bool
p e
e
    | Bool
p = forall e a. e -> Validation (NonEmpty e) a
failure e
e
    | Bool
otherwise = forall e a. a -> Validation e a
Success ()
{-# INLINE failureIf #-}

{- | Returns a 'Failure' unless the given predicate is 'True'.
Returns @'Success' ()@ in case of the predicate is satisfied.

Similar to 'failureIf' with the reversed predicate.

@
'failureUnless' p ≡ 'failureIf' (not p)
@

>>> let shouldFail = (==) "I am a failure"
>>> failureUnless (shouldFail "I am a failure") "doesn't matter"
Success ()
>>> failureUnless (shouldFail "I am NOT a failure") "I told you so"
Failure ("I told you so" :| [])
-}
failureUnless :: Bool -> e -> Validation (NonEmpty e) ()
failureUnless :: forall e. Bool -> e -> Validation (NonEmpty e) ()
failureUnless Bool
p e
e
    | Bool
p = forall e a. a -> Validation e a
Success ()
    | Bool
otherwise = forall e a. e -> Validation (NonEmpty e) a
failure e
e
{-# INLINE failureUnless #-}



{- | Validate all given checks in a 'Foldable'. Returns the 'Success' of the
start element when all checks are successful.


A basic example of usage could look like this:

@
> __let__ validatePassword = 'validateAll'
        [ validateEmptyPassword
        , validateShortPassword
        ]

> 'validateAll' \"VeryStrongPassword\"
'Success' \"VeryStrongPassword\"

> 'validateAll' ""
'Failure' (EmptyPassword :| [ShortPassword])
@
-}
validateAll
    :: (Foldable f, Semigroup e)
    => f (a -> Validation e b)
    -> a
    -> Validation e a
validateAll :: forall (f :: * -> *) e a b.
(Foldable f, Semigroup e) =>
f (a -> Validation e b) -> a -> Validation e a
validateAll f (a -> Validation e b)
fs a
a = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Validation e a
res a -> Validation e b
f -> Validation e a
res forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* a -> Validation e b
f a
a) (forall e a. a -> Validation e a
Success a
a) f (a -> Validation e b)
fs
{-# INLINE validateAll #-}

{- | Applies the given action to 'Validation' if it is 'Failure' and returns the
result. In case of 'Success' the default value is returned.

>>> whenFailure "bar" (Failure 42) (\a -> "foo" <$ print a)
42
"foo"

>>> whenFailure "bar" (Success 42) (\a -> "foo" <$ print a)
"bar"
-}
whenFailure :: Applicative f => x -> Validation e a -> (e -> f x) -> f x
whenFailure :: forall (f :: * -> *) x e a.
Applicative f =>
x -> Validation e a -> (e -> f x) -> f x
whenFailure x
_ (Failure e
e) e -> f x
f = e -> f x
f e
e
whenFailure x
a (Success a
_) e -> f x
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure x
a
{-# INLINE whenFailure #-}

{- | Applies given action to the 'Validation' content if it is 'Failure'.

Similar to 'whenFailure' but the default value is @()@.

>>> whenFailure_ (Success 42) putStrLn
>>> whenFailure_ (Failure "foo") putStrLn
foo
-}
whenFailure_ :: Applicative f => Validation e a -> (e -> f ()) -> f ()
whenFailure_ :: forall (f :: * -> *) e a.
Applicative f =>
Validation e a -> (e -> f ()) -> f ()
whenFailure_ = forall (f :: * -> *) x e a.
Applicative f =>
x -> Validation e a -> (e -> f x) -> f x
whenFailure ()
{-# INLINE whenFailure_ #-}

{- | Monadic version of 'whenFailure'.
Applies monadic action to the given 'Validation' in case of 'Failure'.
Returns the resulting value, or provided default.

>>> whenFailureM "bar" (pure $ Failure 42) (\a -> "foo" <$ print a)
42
"foo"

>>> whenFailureM "bar" (pure $ Success 42) (\a -> "foo" <$ print a)
"bar"
-}
whenFailureM :: Monad m => x -> m (Validation e a) -> (e -> m x) -> m x
whenFailureM :: forall (m :: * -> *) x e a.
Monad m =>
x -> m (Validation e a) -> (e -> m x) -> m x
whenFailureM x
x m (Validation e a)
mv e -> m x
f = m (Validation e a)
mv forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Validation e a
v -> forall (f :: * -> *) x e a.
Applicative f =>
x -> Validation e a -> (e -> f x) -> f x
whenFailure x
x Validation e a
v e -> m x
f
{-# INLINE whenFailureM #-}

{- | Monadic version of 'whenFailure_'.
Applies monadic action to the given 'Validation' in case of 'Failure'.
Similar to 'whenFailureM' but the default is @()@.

>>> whenFailureM_ (pure $ Success 42) putStrLn
>>> whenFailureM_ (pure $ Failure "foo") putStrLn
foo
-}
whenFailureM_ :: Monad m => m (Validation e a) -> (e -> m ()) -> m ()
whenFailureM_ :: forall (m :: * -> *) e a.
Monad m =>
m (Validation e a) -> (e -> m ()) -> m ()
whenFailureM_ m (Validation e a)
mv e -> m ()
f = m (Validation e a)
mv forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Validation e a
v -> forall (f :: * -> *) e a.
Applicative f =>
Validation e a -> (e -> f ()) -> f ()
whenFailure_ Validation e a
v e -> m ()
f
{-# INLINE whenFailureM_ #-}

{- | Applies the given action to 'Validation' if it is 'Success' and returns the
result. In case of 'Failure' the default value is returned.

>>> whenSuccess "bar" (Failure "foo") (\a -> "success!" <$ print a)
"bar"

>>> whenSuccess "bar" (Success 42) (\a -> "success!" <$ print a)
42
"success!"
-}
whenSuccess :: Applicative f => x -> Validation e a -> (a -> f x) -> f x
whenSuccess :: forall (f :: * -> *) x e a.
Applicative f =>
x -> Validation e a -> (a -> f x) -> f x
whenSuccess x
x (Failure  e
_) a -> f x
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure x
x
whenSuccess x
_ (Success a
a) a -> f x
f  = a -> f x
f a
a
{-# INLINE whenSuccess #-}

{- | Applies given action to the 'Validation' content if it is 'Success'.

Similar to 'whenSuccess' but the default value is @()@.

>>> whenSuccess_ (Failure "foo") print
>>> whenSuccess_ (Success 42) print
42
-}
whenSuccess_ :: Applicative f => Validation e a -> (a -> f ()) -> f ()
whenSuccess_ :: forall (f :: * -> *) e a.
Applicative f =>
Validation e a -> (a -> f ()) -> f ()
whenSuccess_ = forall (f :: * -> *) x e a.
Applicative f =>
x -> Validation e a -> (a -> f x) -> f x
whenSuccess ()
{-# INLINE whenSuccess_ #-}

{- | Monadic version of 'whenSuccess'.
Applies monadic action to the given 'Validation' in case of 'Success'.
Returns the resulting value, or provided default.

>>> whenSuccessM "bar" (pure $ Failure "foo") (\a -> "success!" <$ print a)
"bar"

>>> whenSuccessM "bar" (pure $ Success 42) (\a -> "success!" <$ print a)
42
"success!"
-}
whenSuccessM :: Monad m => x -> m (Validation e a) -> (a -> m x) -> m x
whenSuccessM :: forall (m :: * -> *) x e a.
Monad m =>
x -> m (Validation e a) -> (a -> m x) -> m x
whenSuccessM x
x m (Validation e a)
mv a -> m x
f = m (Validation e a)
mv forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Validation e a
v -> forall (f :: * -> *) x e a.
Applicative f =>
x -> Validation e a -> (a -> f x) -> f x
whenSuccess x
x Validation e a
v a -> m x
f
{-# INLINE whenSuccessM #-}

{- | Monadic version of 'whenSuccess_'.
Applies monadic action to the given 'Validation' in case of 'Success'.
Similar to 'whenSuccessM' but the default is @()@.

>>> whenSuccessM_ (pure $ Failure "foo") print
>>> whenSuccessM_ (pure $ Success 42) print
42
-}
whenSuccessM_ :: Monad m => m (Validation e a) -> (a -> m ()) -> m ()
whenSuccessM_ :: forall (m :: * -> *) e a.
Monad m =>
m (Validation e a) -> (a -> m ()) -> m ()
whenSuccessM_ m (Validation e a)
mv a -> m ()
f = m (Validation e a)
mv forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Validation e a
v -> forall (f :: * -> *) e a.
Applicative f =>
Validation e a -> (a -> f ()) -> f ()
whenSuccess_ Validation e a
v a -> m ()
f
{-# INLINE whenSuccessM_ #-}


{- | Maps 'Failure' of 'Validation' to 'Just'.

>>> failureToMaybe (Failure True)
Just True
>>> failureToMaybe (Success "aba")
Nothing
-}
failureToMaybe :: Validation e a -> Maybe e
failureToMaybe :: forall e a. Validation e a -> Maybe e
failureToMaybe = forall e x a. (e -> x) -> (a -> x) -> Validation e a -> x
validation forall a. a -> Maybe a
Just (forall a b. a -> b -> a
const forall a. Maybe a
Nothing)
{-# INLINE failureToMaybe #-}

{- | Maps 'Success' of 'Validation' to 'Just'.

>>> successToMaybe (Failure True)
Nothing
>>> successToMaybe (Success "aba")
Just "aba"
-}
successToMaybe :: Validation e a -> Maybe a
successToMaybe :: forall e a. Validation e a -> Maybe a
successToMaybe = forall e x a. (e -> x) -> (a -> x) -> Validation e a -> x
validation (forall a b. a -> b -> a
const forall a. Maybe a
Nothing) forall a. a -> Maybe a
Just
{-# INLINE successToMaybe #-}

{- | Maps 'Just' to 'Failure' In case of 'Nothing' it wraps the given default
value into 'Success'.

>>> maybeToFailure True (Just "aba")
Failure "aba"
>>> maybeToFailure True Nothing
Success True
-}
maybeToFailure :: a -> Maybe e -> Validation e a
maybeToFailure :: forall a e. a -> Maybe e -> Validation e a
maybeToFailure a
a = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall e a. a -> Validation e a
Success a
a) forall e a. e -> Validation e a
Failure
{-# INLINE maybeToFailure #-}

{- | Maps 'Just' to 'Success'. In case of 'Nothing' it wraps the given default
value into 'Failure'

>>> maybeToSuccess True (Just "aba")
Success "aba"
>>> maybeToSuccess True Nothing
Failure True
-}
maybeToSuccess :: e -> Maybe a -> Validation e a
maybeToSuccess :: forall e a. e -> Maybe a -> Validation e a
maybeToSuccess e
e = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall e a. e -> Validation e a
Failure e
e) forall e a. a -> Validation e a
Success
{-# INLINE maybeToSuccess #-}