{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Relude.Extra.Validation
(
Validation(..)
, validationToEither
, eitherToValidation
) where
import GHC.TypeLits (ErrorMessage (..), TypeError)
import Relude
data Validation e a
= Failure e
| Success a
deriving (Validation e a -> Validation e a -> Bool
(Validation e a -> Validation e a -> Bool)
-> (Validation e a -> Validation e a -> Bool)
-> Eq (Validation e a)
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, Eq (Validation e a)
Eq (Validation e a) =>
(Validation e a -> Validation e a -> Ordering)
-> (Validation e a -> Validation e a -> Bool)
-> (Validation e a -> Validation e a -> Bool)
-> (Validation e a -> Validation e a -> Bool)
-> (Validation e a -> Validation e a -> Bool)
-> (Validation e a -> Validation e a -> Validation e a)
-> (Validation e a -> Validation e a -> Validation e a)
-> Ord (Validation e a)
Validation e a -> Validation e a -> Bool
Validation e a -> Validation e a -> Ordering
Validation e a -> Validation e a -> Validation e a
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
$cp1Ord :: forall e a. (Ord e, Ord a) => Eq (Validation e a)
Ord, Int -> Validation e a -> ShowS
[Validation e a] -> ShowS
Validation e a -> String
(Int -> Validation e a -> ShowS)
-> (Validation e a -> String)
-> ([Validation e a] -> ShowS)
-> Show (Validation e a)
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)
instance Functor (Validation e) where
fmap :: (a -> b) -> Validation e a -> Validation e b
fmap :: (a -> b) -> Validation e a -> Validation e b
fmap _ (Failure e :: e
e) = e -> Validation e b
forall e a. e -> Validation e a
Failure e
e
fmap f :: a -> b
f (Success a :: a
a) = b -> Validation e b
forall e a. a -> Validation e a
Success (a -> b
f a
a)
{-# INLINE fmap #-}
(<$) :: a -> Validation e b -> Validation e a
x :: a
x <$ :: a -> Validation e b -> Validation e a
<$ Success _ = a -> Validation e a
forall e a. a -> Validation e a
Success a
x
_ <$ Failure e :: e
e = e -> Validation e a
forall e a. e -> Validation e a
Failure e
e
{-# INLINE (<$) #-}
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
(<>) = (a -> a -> 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 a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>)
{-# INLINE (<>) #-}
instance (Semigroup e, Monoid a) => Monoid (Validation e a) where
mempty :: Validation e a
mempty :: Validation e a
mempty = a -> Validation e a
forall e a. a -> Validation e a
Success a
forall a. Monoid a => a
mempty
{-# INLINE mempty #-}
instance Semigroup e => Applicative (Validation e) where
pure :: a -> Validation e a
pure :: a -> Validation e a
pure = a -> Validation e a
forall e a. a -> Validation e a
Success
{-# INLINE pure #-}
(<*>) :: Validation e (a -> b) -> Validation e a -> Validation e b
Failure e :: e
e <*> :: Validation e (a -> b) -> Validation e a -> Validation e b
<*> b :: Validation e a
b = e -> Validation e b
forall e a. e -> Validation e a
Failure (e -> Validation e b) -> e -> Validation e b
forall a b. (a -> b) -> a -> b
$ case Validation e a
b of
Failure e' :: e
e' -> e
e e -> e -> e
forall a. Semigroup a => a -> a -> a
<> e
e'
Success _ -> e
e
Success _ <*> Failure e :: e
e = e -> Validation e b
forall e a. e -> Validation e a
Failure e
e
Success f :: a -> b
f <*> Success a :: a
a = b -> Validation e b
forall e a. a -> Validation e a
Success (a -> b
f a
a)
{-# INLINE (<*>) #-}
(*>) :: Validation e a -> Validation e b -> Validation e b
Failure e :: e
e *> :: Validation e a -> Validation e b -> Validation e b
*> b :: Validation e b
b = e -> Validation e b
forall e a. e -> Validation e a
Failure (e -> Validation e b) -> e -> Validation e b
forall a b. (a -> b) -> a -> b
$ case Validation e b
b of
Failure e' :: e
e' -> e
e e -> e -> e
forall a. Semigroup a => a -> a -> a
<> e
e'
Success _ -> e
e
Success _ *> Failure e :: e
e = e -> Validation e b
forall e a. e -> Validation e a
Failure e
e
Success _ *> Success b :: b
b = b -> Validation e b
forall e a. a -> Validation e a
Success b
b
{-# INLINE (*>) #-}
(<*) :: Validation e a -> Validation e b -> Validation e a
Failure e :: e
e <* :: Validation e a -> Validation e b -> Validation e a
<* b :: Validation e b
b = e -> Validation e a
forall e a. e -> Validation e a
Failure (e -> Validation e a) -> e -> Validation e a
forall a b. (a -> b) -> a -> b
$ case Validation e b
b of
Failure e' :: e
e' -> e
e e -> e -> e
forall a. Semigroup a => a -> a -> a
<> e
e'
Success _ -> e
e
Success _ <* Failure e :: e
e = e -> Validation e a
forall e a. e -> Validation e a
Failure e
e
Success a :: a
a <* Success _ = a -> Validation e a
forall e a. a -> Validation e a
Success a
a
{-# INLINE (<*) #-}
instance (Semigroup e, Monoid e) => Alternative (Validation e) where
empty :: Validation e a
empty :: Validation e a
empty = e -> Validation e a
forall e a. e -> Validation e a
Failure e
forall a. Monoid a => a
mempty
{-# INLINE empty #-}
(<|>) :: Validation e a -> Validation e a -> Validation e a
s :: Validation e a
s@Success{} <|> :: Validation e a -> Validation e a -> Validation e a
<|> _ = Validation e a
s
_ <|> s :: Validation e a
s@Success{} = Validation e a
s
Failure e :: e
e <|> Failure e' :: e
e' = e -> Validation e a
forall e a. e -> Validation e a
Failure (e
e e -> e -> e
forall a. Semigroup a => a -> a -> a
<> e
e')
{-# INLINE (<|>) #-}
instance Foldable (Validation e) where
fold :: Monoid m => Validation e m -> m
fold :: Validation e m -> m
fold (Success a :: m
a) = m
a
fold (Failure _) = m
forall a. Monoid a => a
mempty
{-# INLINE fold #-}
foldMap :: Monoid m => (a -> m) -> Validation e a -> m
foldMap :: (a -> m) -> Validation e a -> m
foldMap _ (Failure _) = m
forall a. Monoid a => a
mempty
foldMap f :: a -> m
f (Success a :: a
a) = a -> m
f a
a
{-# INLINE foldMap #-}
foldr :: (a -> b -> b) -> b -> Validation e a -> b
foldr :: (a -> b -> b) -> b -> Validation e a -> b
foldr f :: a -> b -> b
f x :: b
x (Success a :: a
a) = a -> b -> b
f a
a b
x
foldr _ x :: b
x (Failure _) = b
x
{-# INLINE foldr #-}
instance Traversable (Validation e) where
traverse :: Applicative f => (a -> f b) -> Validation e a -> f (Validation e b)
traverse :: (a -> f b) -> Validation e a -> f (Validation e b)
traverse f :: a -> f b
f (Success a :: a
a) = b -> Validation e b
forall e a. a -> Validation e a
Success (b -> Validation e b) -> f b -> f (Validation e b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
a
traverse _ (Failure e :: e
e) = Validation e b -> f (Validation e b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> Validation e b
forall e a. e -> Validation e a
Failure e
e)
{-# INLINE traverse #-}
sequenceA :: Applicative f => Validation e (f a) -> f (Validation e a)
sequenceA :: Validation e (f a) -> f (Validation e a)
sequenceA = (f a -> f a) -> Validation e (f a) -> f (Validation e a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse f a -> f a
forall a. a -> a
id
{-# INLINE sequenceA #-}
instance Bifunctor Validation where
bimap :: (e -> d) -> (a -> b) -> Validation e a -> Validation d b
bimap :: (e -> d) -> (a -> b) -> Validation e a -> Validation d b
bimap f :: e -> d
f _ (Failure e :: e
e) = d -> Validation d b
forall e a. e -> Validation e a
Failure (e -> d
f e
e)
bimap _ g :: a -> b
g (Success a :: a
a) = b -> Validation d b
forall e a. a -> Validation e a
Success (a -> b
g a
a)
{-# INLINE bimap #-}
first :: (e -> d) -> Validation e a -> Validation d a
first :: (e -> d) -> Validation e a -> Validation d a
first f :: e -> d
f (Failure e :: e
e) = d -> Validation d a
forall e a. e -> Validation e a
Failure (e -> d
f e
e)
first _ (Success a :: a
a) = a -> Validation d a
forall e a. a -> Validation e a
Success a
a
{-# INLINE first #-}
second :: (a -> b) -> Validation e a -> Validation e b
second :: (a -> b) -> Validation e a -> Validation e b
second _ (Failure e :: e
e) = e -> Validation e b
forall e a. e -> Validation e a
Failure e
e
second g :: a -> b
g (Success a :: a
a) = b -> Validation e b
forall e a. a -> Validation e a
Success (a -> b
g a
a)
{-# INLINE second #-}
#if MIN_VERSION_base(4,10,0)
instance Bifoldable Validation where
bifoldMap :: Monoid m => (e -> m) -> (a -> m) -> Validation e a -> m
bifoldMap :: (e -> m) -> (a -> m) -> Validation e a -> m
bifoldMap f :: e -> m
f _ (Failure e :: e
e) = e -> m
f e
e
bifoldMap _ g :: a -> m
g (Success a :: a
a) = a -> m
g a
a
{-# INLINE bifoldMap #-}
instance Bitraversable Validation where
bitraverse :: Applicative f
=> (e -> f d) -> (a -> f b) -> Validation e a -> f (Validation d b)
bitraverse :: (e -> f d) -> (a -> f b) -> Validation e a -> f (Validation d b)
bitraverse f :: e -> f d
f _ (Failure e :: e
e) = d -> Validation d b
forall e a. e -> Validation e a
Failure (d -> Validation d b) -> f d -> f (Validation d b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> e -> f d
f e
e
bitraverse _ g :: a -> f b
g (Success a :: a
a) = b -> Validation d b
forall e a. a -> Validation e a
Success (b -> Validation d b) -> f b -> f (Validation d b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
g a
a
{-# INLINE bitraverse #-}
#endif
validationToEither :: Validation e a -> Either e a
validationToEither :: Validation e a -> Either e a
validationToEither = \case
Failure e :: e
e -> e -> Either e a
forall a b. a -> Either a b
Left e
e
Success a :: a
a -> a -> Either e a
forall a b. b -> Either a b
Right a
a
{-# INLINE validationToEither #-}
eitherToValidation :: Either e a -> Validation e a
eitherToValidation :: Either e a -> Validation e a
eitherToValidation = \case
Left e :: e
e -> e -> Validation e a
forall e a. e -> Validation e a
Failure e
e
Right a :: a
a -> a -> Validation e a
forall e a. a -> Validation e a
Success a
a
{-# INLINE eitherToValidation #-}
instance (NoValidationMonadError, Semigroup e) => Monad (Validation e) where
return :: a -> Validation e a
return = Text -> a -> Validation e a
forall a t. (HasCallStack, IsText t) => t -> a
error "Unreachable Validation instance of Monad"
>>= :: Validation e a -> (a -> Validation e b) -> Validation e b
(>>=) = Text -> Validation e a -> (a -> Validation e b) -> Validation e b
forall a t. (HasCallStack, IsText t) => t -> a
error "Unreachable Validation instance of Monad"
type family NoValidationMonadError :: Constraint where
NoValidationMonadError = TypeError
( 'Text "Type 'Validation' doesn't have lawful 'Monad' instance"
':$$: 'Text "which means that you can't use 'Monad' methods with 'Validation'."
)