module Data.Validation
(
AccValidation(..)
, _Failure
, _Success
, Validate(..)
) where
import Control.Applicative(Applicative((<*>), pure), (<$>))
import Control.Lens.Getter((^.))
import Control.Lens.Iso(Swapped(..), Iso, iso)
import Control.Lens.Prism(Prism, prism)
import Control.Lens.Review(( # ))
import Data.Bifoldable(Bifoldable(bifoldr))
import Data.Bifunctor(Bifunctor(bimap))
import Data.Bitraversable(Bitraversable(bitraverse))
import Data.Data(Data)
import Data.Either(Either(Left, Right))
import Data.Eq(Eq)
import Data.Foldable(Foldable(foldr))
import Data.Function(id)
import Data.Functor(Functor(fmap))
import Data.Functor.Alt(Alt((<!>)))
import Data.Functor.Apply(Apply((<.>)))
import Data.Monoid(Monoid(mappend, mempty))
import Data.Ord(Ord)
import Data.Semigroup(Semigroup((<>)))
import Data.Traversable(Traversable(traverse))
import Data.Typeable(Typeable)
import Prelude(Show)
data AccValidation err a =
AccFailure err
| AccSuccess a
deriving (Eq, Ord, Show, Data, Typeable)
fmapAccValidation ::
(a -> b)
-> AccValidation err a
-> AccValidation err b
fmapAccValidation _ (AccFailure e) =
AccFailure e
fmapAccValidation f (AccSuccess a) =
AccSuccess (f a)
instance Functor (AccValidation err) where
fmap =
fmapAccValidation
apAccValidation ::
Semigroup err =>
AccValidation err (a -> b)
-> AccValidation err a
-> AccValidation err b
AccFailure e1 `apAccValidation` AccFailure e2 =
AccFailure (e1 <> e2)
AccFailure e1 `apAccValidation` AccSuccess _ =
AccFailure e1
AccSuccess _ `apAccValidation` AccFailure e2 =
AccFailure e2
AccSuccess f `apAccValidation` AccSuccess a =
AccSuccess (f a)
instance Semigroup err => Apply (AccValidation err) where
(<.>) =
apAccValidation
instance Semigroup err => Applicative (AccValidation err) where
pure =
AccSuccess
(<*>) =
(<.>)
altAccValidation ::
AccValidation err a
-> AccValidation err a
-> AccValidation err a
AccFailure _ `altAccValidation` x =
x
AccSuccess a `altAccValidation` _ =
AccSuccess a
instance Alt (AccValidation err) where
(<!>) =
altAccValidation
foldrAccValidation ::
(a -> b -> b)
-> b
-> AccValidation err a -> b
foldrAccValidation f x (AccSuccess a) =
f a x
foldrAccValidation _ x (AccFailure _) =
x
instance Foldable (AccValidation err) where
foldr =
foldrAccValidation
traverseAccValidation ::
Applicative f =>
(a -> f b)
-> AccValidation err a
-> f (AccValidation err b)
traverseAccValidation f (AccSuccess a) =
AccSuccess <$> f a
traverseAccValidation _ (AccFailure e) =
pure (AccFailure e)
instance Traversable (AccValidation err) where
traverse =
traverseAccValidation
bimapAccValidation ::
(err -> f)
-> (a -> b)
-> AccValidation err a
-> AccValidation f b
bimapAccValidation f _ (AccFailure e) =
AccFailure (f e)
bimapAccValidation _ g (AccSuccess a) =
AccSuccess (g a)
instance Bifunctor AccValidation where
bimap =
bimapAccValidation
bifoldrAccValidation ::
(x -> a -> b)
-> (y -> a -> b)
-> a
-> AccValidation x y
-> b
bifoldrAccValidation _ g x (AccSuccess a) =
g a x
bifoldrAccValidation f _ x (AccFailure e) =
f e x
instance Bifoldable AccValidation where
bifoldr =
bifoldrAccValidation
bitraverseAccValidation ::
Functor f =>
(x -> f err)
-> (y -> f a)
-> AccValidation x y
-> f (AccValidation err a)
bitraverseAccValidation _ g (AccSuccess a) =
AccSuccess <$> g a
bitraverseAccValidation f _ (AccFailure e) =
AccFailure <$> f e
instance Bitraversable AccValidation where
bitraverse =
bitraverseAccValidation
appsAccValidation ::
Semigroup err =>
AccValidation err a
-> AccValidation err a
-> AccValidation err a
AccFailure e1 `appsAccValidation` AccFailure e2 =
AccFailure (e1 <> e2)
AccFailure _ `appsAccValidation` AccSuccess a2 =
AccSuccess a2
AccSuccess a1 `appsAccValidation` AccFailure _ =
AccSuccess a1
AccSuccess a1 `appsAccValidation` AccSuccess _ =
AccSuccess a1
instance Semigroup e => Semigroup (AccValidation e a) where
(<>) =
appsAccValidation
appmAccValidation ::
Monoid err =>
AccValidation err a
-> AccValidation err a
-> AccValidation err a
AccFailure e1 `appmAccValidation` AccFailure e2 =
AccFailure (e1 `mappend` e2)
AccFailure _ `appmAccValidation` AccSuccess a2 =
AccSuccess a2
AccSuccess a1 `appmAccValidation` AccFailure _ =
AccSuccess a1
AccSuccess a1 `appmAccValidation` AccSuccess _ =
AccSuccess a1
emptyAccValidation ::
Monoid err =>
AccValidation err a
emptyAccValidation =
AccFailure mempty
instance Monoid e => Monoid (AccValidation e a) where
mappend =
appmAccValidation
mempty =
emptyAccValidation
_EitherV ::
Validate f =>
Iso (f e a) (f g b) (Either e a) (Either g b)
_EitherV =
iso
(\x -> case x ^. _AccValidation of
AccFailure e -> Left e
AccSuccess a -> Right a)
(\x -> _AccValidation # case x of
Left e -> AccFailure e
Right a -> AccSuccess a)
class Validate f where
_AccValidation ::
Iso (f e a) (f g b) (AccValidation e a) (AccValidation g b)
_Either ::
Iso (f e a) (f g b) (Either e a) (Either g b)
_Either =
_EitherV
_AccValidationEitherIso ::
Iso (AccValidation e a) (AccValidation g b) (Either e a) (Either g b)
_AccValidationEitherIso =
iso
(\x -> case x of
AccFailure e -> Left e
AccSuccess a -> Right a)
(\x -> case x of
Left e -> AccFailure e
Right a -> AccSuccess a)
instance Validate AccValidation where
_AccValidation =
id
_Either =
_AccValidationEitherIso
_EitherAccValidationIso ::
Iso (Either e a) (Either g b) (AccValidation e a) (AccValidation g b)
_EitherAccValidationIso =
iso
(\x -> case x of
Left e -> AccFailure e
Right a -> AccSuccess a)
(\x -> case x of
AccFailure e -> Left e
AccSuccess a -> Right a)
instance Validate Either where
_AccValidation =
_EitherAccValidationIso
_Either =
id
_Failure ::
Validate f =>
Prism (f e1 a) (f e2 a) e1 e2
_Failure =
prism
(\x -> _Either # Left x)
(\x -> case x ^. _Either of
Left e -> Right e
Right a -> Left (_Either # Right a))
_Success ::
Validate f =>
Prism (f e a) (f e b) a b
_Success =
prism
(\x -> _Either # Right x)
(\x -> case x ^. _Either of
Left e -> Left (_Either # Left e)
Right a -> Right a)
swappedAccValidation ::
Iso (AccValidation e a) (AccValidation f b) (AccValidation a e) (AccValidation b f)
swappedAccValidation =
iso
(\v -> case v of
AccFailure e -> AccSuccess e
AccSuccess a -> AccFailure a)
(\v -> case v of
AccFailure a -> AccSuccess a
AccSuccess e -> AccFailure e)
instance Swapped AccValidation where
swapped =
swappedAccValidation