validators-0.0.1: lib/Data/Validation.hs
-- | This module defines the 'Validation' data type.
--
-- Most functionality is the same as in the
-- <http://hackage.haskell.org/package/validation-1.1 validation> library,
-- but the module doesn't provide certain typeclass instances that require
-- a dependency on the lens library.
module Data.Validation
( Validation (..),
toEither,
fromEither,
)
where
import Data.Bifoldable
import Data.Bifunctor
import Data.Bitraversable
-- | A 'Validation' is very similar to 'Either' in that it contains a value of type /e/ or /a/.
-- In contrast to Either however, Validation accumulates all errors it comes
-- across in it's 'Applicative' instance.
--
-- A complete example where Validation is used can be found
-- <https://github.com/luc-tielen/validators.git here>.
data Validation err a
= Failure !err
| Success !a
deriving (Eq, Show, Ord)
instance Functor (Validation err) where
fmap _ (Failure err) = Failure err
fmap f (Success a) = Success (f a)
{-# INLINE fmap #-}
instance Bifunctor Validation where
bimap f _ (Failure e) = Failure (f e)
bimap _ g (Success a) = Success (g a)
{-# INLINE bimap #-}
instance Foldable (Validation err) where
foldMap f (Success a) = f a
foldMap _ _ = mempty
{-# INLINE foldMap #-}
instance Bifoldable Validation where
bifoldMap f _ (Failure e) = f e
bifoldMap _ g (Success a) = g a
{-# INLINE bifoldMap #-}
instance Traversable (Validation err) where
traverse f (Success a) = Success <$> f a
traverse _ (Failure e) = pure (Failure e)
{-# INLINE traverse #-}
instance Bitraversable Validation where
bitraverse _ g (Success a) = Success <$> g a
bitraverse f _ (Failure e) = Failure <$> f e
{-# INLINE bitraverse #-}
instance Semigroup err => Applicative (Validation err) where
Failure e1 <*> Failure e2 = Failure (e1 <> e2)
Failure e1 <*> _ = Failure e1
_ <*> Failure e2 = Failure e2
Success f <*> Success a = Success (f a)
{-# INLINE (<*>) #-}
pure = Success
{-# INLINE pure #-}
-- | Conversion function from 'Validation' to 'Either'.
--
-- >>> toEither (Failure 1)
-- Left 1
-- >>> toEither (Success True)
-- Right True
toEither :: Validation err a -> Either err a
toEither v = case v of
Failure e -> Left e
Success a -> Right a
{-# INLINE toEither #-}
-- | Conversion function from 'Either' to 'Validation'.
--
-- >>> fromEither (Left 1)
-- Failure 1
-- >>> fromEither (Right True)
-- Success True
fromEither :: Either err a -> Validation err a
fromEither e = case e of
Left a -> Failure a
Right b -> Success b
{-# INLINE fromEither #-}