{-# LANGUAGE 
 LambdaCase, DerivingStrategies, DerivingVia, StandaloneDeriving, KindSignatures, GeneralizedNewtypeDeriving,
 PolyKinds, TypeOperators,
 DefaultSignatures, InstanceSigs, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, UndecidableInstances
 #-}
module Control.Validation.Class(
    -- * Checkable
    -- $checkable
    validate, validate',
    CheckChain(..), overChain, (+?+), singleChain,
    Validatable(..), 
    TrivialCheck(..),

    -- ** Helper for deriving Validatable
    -- $derivHelper

    -- * Reexports
                         
) where

import Data.Foldable(fold)
import Data.Kind(Type)
import Data.Void(Void)
import Data.Int(Int8, Int16, Int32, Int64)
import Control.Validation.Check
import Data.Functor.Identity(Identity(..))
import Data.Sequence(Seq)
import GHC.Generics    
import Data.Functor.Contravariant.Compose(ComposeFC(..)) 
import Data.Functor.Contravariant(Contravariant(..))
import Data.Functor.Contravariant.Divisible(Divisible(..), Decidable(..))
import Control.Monad.Morph(MFunctor(..))    
------------------------------------------------------------------------------------------------------
-- $checkable
-- = The 'Validatable' typeclass. 
-- /Note/: It is not inteded to be used for testing of
-- internal integrity of types, i.e. it does not check if a 'Text' has a valid internal 
-- representation. For testing internal integrity please use the package
--  (validity)[https://stackage.org/package/validity].
-- The typeclass is split up into three parts: 
-- 
-- * 'checkChain':  A list of checks that will be performed in 
-- that order. This has to be provided to give an instance.
-- For the reason why it is given as a list and the checks are 
-- not combined via '(<>)', see the point for `isValid`.
--
-- * 'defaulCheck': A check performing all checks of 'checkChain'
--
-- > defaultCheck = fold checkChain
--
-- * 'isValid':     A function determining whether a value is valid.
-- This functions stops checking after the first of the checks
-- from 'checkChain' fails .This function is the reason why we
-- need the 'checkChain', as a 'Check' constructed by '(<>)'
-- goes through all operands, so `passed $ runCheck (shortCheck <> longCheck) unvalidatedInput`
-- evalutes the argument with `longCheck` even if `shortCheck` failed.
-- But if we define
-- 
-- > instance Validatable e m T where
-- >   checkChain = CheckChain [ shortCheck, longCheck ]
-- 
-- then `isValid unvalidatedInput` stops after `shortCheck` failed.


newtype CheckChain (e :: Type) (m :: Type -> Type) (a :: Type) = 
    CheckChain { CheckChain e m a -> [Check e m a]
runCheckChain :: [ Check e m a ] }
        deriving newtype ( Semigroup (CheckChain e m a)
CheckChain e m a
Semigroup (CheckChain e m a) =>
CheckChain e m a
-> (CheckChain e m a -> CheckChain e m a -> CheckChain e m a)
-> ([CheckChain e m a] -> CheckChain e m a)
-> Monoid (CheckChain e m a)
[CheckChain e m a] -> CheckChain e m a
CheckChain e m a -> CheckChain e m a -> CheckChain e m a
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall e (m :: * -> *) a. Semigroup (CheckChain e m a)
forall e (m :: * -> *) a. CheckChain e m a
forall e (m :: * -> *) a. [CheckChain e m a] -> CheckChain e m a
forall e (m :: * -> *) a.
CheckChain e m a -> CheckChain e m a -> CheckChain e m a
mconcat :: [CheckChain e m a] -> CheckChain e m a
$cmconcat :: forall e (m :: * -> *) a. [CheckChain e m a] -> CheckChain e m a
mappend :: CheckChain e m a -> CheckChain e m a -> CheckChain e m a
$cmappend :: forall e (m :: * -> *) a.
CheckChain e m a -> CheckChain e m a -> CheckChain e m a
mempty :: CheckChain e m a
$cmempty :: forall e (m :: * -> *) a. CheckChain e m a
$cp1Monoid :: forall e (m :: * -> *) a. Semigroup (CheckChain e m a)
Monoid, b -> CheckChain e m a -> CheckChain e m a
NonEmpty (CheckChain e m a) -> CheckChain e m a
CheckChain e m a -> CheckChain e m a -> CheckChain e m a
(CheckChain e m a -> CheckChain e m a -> CheckChain e m a)
-> (NonEmpty (CheckChain e m a) -> CheckChain e m a)
-> (forall b.
    Integral b =>
    b -> CheckChain e m a -> CheckChain e m a)
-> Semigroup (CheckChain e m a)
forall b. Integral b => b -> CheckChain e m a -> CheckChain e m a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall e (m :: * -> *) a.
NonEmpty (CheckChain e m a) -> CheckChain e m a
forall e (m :: * -> *) a.
CheckChain e m a -> CheckChain e m a -> CheckChain e m a
forall e (m :: * -> *) a b.
Integral b =>
b -> CheckChain e m a -> CheckChain e m a
stimes :: b -> CheckChain e m a -> CheckChain e m a
$cstimes :: forall e (m :: * -> *) a b.
Integral b =>
b -> CheckChain e m a -> CheckChain e m a
sconcat :: NonEmpty (CheckChain e m a) -> CheckChain e m a
$csconcat :: forall e (m :: * -> *) a.
NonEmpty (CheckChain e m a) -> CheckChain e m a
<> :: CheckChain e m a -> CheckChain e m a -> CheckChain e m a
$c<> :: forall e (m :: * -> *) a.
CheckChain e m a -> CheckChain e m a -> CheckChain e m a
Semigroup ) 
        deriving (b -> CheckChain e m b -> CheckChain e m a
(a -> b) -> CheckChain e m b -> CheckChain e m a
(forall a b. (a -> b) -> CheckChain e m b -> CheckChain e m a)
-> (forall b a. b -> CheckChain e m b -> CheckChain e m a)
-> Contravariant (CheckChain e m)
forall b a. b -> CheckChain e m b -> CheckChain e m a
forall a b. (a -> b) -> CheckChain e m b -> CheckChain e m a
forall e (m :: * -> *) b a.
b -> CheckChain e m b -> CheckChain e m a
forall e (m :: * -> *) a b.
(a -> b) -> CheckChain e m b -> CheckChain e m a
forall (f :: * -> *).
(forall a b. (a -> b) -> f b -> f a)
-> (forall b a. b -> f b -> f a) -> Contravariant f
>$ :: b -> CheckChain e m b -> CheckChain e m a
$c>$ :: forall e (m :: * -> *) b a.
b -> CheckChain e m b -> CheckChain e m a
contramap :: (a -> b) -> CheckChain e m b -> CheckChain e m a
$ccontramap :: forall e (m :: * -> *) a b.
(a -> b) -> CheckChain e m b -> CheckChain e m a
Contravariant, Contravariant (CheckChain e m)
CheckChain e m a
Contravariant (CheckChain e m) =>
(forall a b c.
 (a -> (b, c))
 -> CheckChain e m b -> CheckChain e m c -> CheckChain e m a)
-> (forall a. CheckChain e m a) -> Divisible (CheckChain e m)
(a -> (b, c))
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
forall a. CheckChain e m a
forall a b c.
(a -> (b, c))
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
forall e (m :: * -> *).
Applicative m =>
Contravariant (CheckChain e m)
forall e (m :: * -> *) a. Applicative m => CheckChain e m a
forall e (m :: * -> *) a b c.
Applicative m =>
(a -> (b, c))
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
forall (f :: * -> *).
Contravariant f =>
(forall a b c. (a -> (b, c)) -> f b -> f c -> f a)
-> (forall a. f a) -> Divisible f
conquer :: CheckChain e m a
$cconquer :: forall e (m :: * -> *) a. Applicative m => CheckChain e m a
divide :: (a -> (b, c))
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
$cdivide :: forall e (m :: * -> *) a b c.
Applicative m =>
(a -> (b, c))
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
$cp1Divisible :: forall e (m :: * -> *).
Applicative m =>
Contravariant (CheckChain e m)
Divisible, Divisible (CheckChain e m)
Divisible (CheckChain e m) =>
(forall a. (a -> Void) -> CheckChain e m a)
-> (forall a b c.
    (a -> Either b c)
    -> CheckChain e m b -> CheckChain e m c -> CheckChain e m a)
-> Decidable (CheckChain e m)
(a -> Void) -> CheckChain e m a
(a -> Either b c)
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
forall a. (a -> Void) -> CheckChain e m a
forall a b c.
(a -> Either b c)
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
forall e (m :: * -> *). Applicative m => Divisible (CheckChain e m)
forall e (m :: * -> *) a.
Applicative m =>
(a -> Void) -> CheckChain e m a
forall e (m :: * -> *) a b c.
Applicative m =>
(a -> Either b c)
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
forall (f :: * -> *).
Divisible f =>
(forall a. (a -> Void) -> f a)
-> (forall a b c. (a -> Either b c) -> f b -> f c -> f a)
-> Decidable f
choose :: (a -> Either b c)
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
$cchoose :: forall e (m :: * -> *) a b c.
Applicative m =>
(a -> Either b c)
-> CheckChain e m b -> CheckChain e m c -> CheckChain e m a
lose :: (a -> Void) -> CheckChain e m a
$close :: forall e (m :: * -> *) a.
Applicative m =>
(a -> Void) -> CheckChain e m a
$cp1Decidable :: forall e (m :: * -> *). Applicative m => Divisible (CheckChain e m)
Decidable) via (ComposeFC [] (Check e m))

instance MFunctor (CheckChain e) where
  hoist :: (forall a. m a -> n a) -> CheckChain e m b -> CheckChain e n b
hoist f :: forall a. m a -> n a
f = (Check e m b -> Check e n b)
-> CheckChain e m b -> CheckChain e n b
forall e (m :: * -> *) a e' (n :: * -> *) b.
(Check e m a -> Check e' n b)
-> CheckChain e m a -> CheckChain e' n b
overChain ((forall a. m a -> n a) -> Check e m b -> Check e n b
forall k (t :: (* -> *) -> k -> *) (m :: * -> *) (n :: * -> *)
       (b :: k).
(MFunctor t, Monad m) =>
(forall a. m a -> n a) -> t m b -> t n b
hoist forall a. m a -> n a
f)

overChain :: (Check e m a -> Check e' n b) -> CheckChain e m a -> CheckChain e' n b
overChain :: (Check e m a -> Check e' n b)
-> CheckChain e m a -> CheckChain e' n b
overChain f :: Check e m a -> Check e' n b
f = [Check e' n b] -> CheckChain e' n b
forall e (m :: * -> *) a. [Check e m a] -> CheckChain e m a
CheckChain ([Check e' n b] -> CheckChain e' n b)
-> (CheckChain e m a -> [Check e' n b])
-> CheckChain e m a
-> CheckChain e' n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Check e m a -> Check e' n b) -> [Check e m a] -> [Check e' n b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Check e m a -> Check e' n b
f ([Check e m a] -> [Check e' n b])
-> (CheckChain e m a -> [Check e m a])
-> CheckChain e m a
-> [Check e' n b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CheckChain e m a -> [Check e m a]
forall e (m :: * -> *) a. CheckChain e m a -> [Check e m a]
runCheckChain             

-- | Convenience synonym.
{-# INLINE (+?+) #-}
(+?+) :: CheckChain e m a -> CheckChain e m a -> CheckChain e m a 
+?+ :: CheckChain e m a -> CheckChain e m a -> CheckChain e m a
(+?+) = CheckChain e m a -> CheckChain e m a -> CheckChain e m a
forall a. Semigroup a => a -> a -> a
(<>)
infixr 5 +?+ -- so it behaves like list concatenation

{-# INLINE emptyChain #-}
-- | The checkchain that contains no checks
emptyChain :: CheckChain e m a
emptyChain :: CheckChain e m a
emptyChain = CheckChain e m a
forall a. Monoid a => a
mempty


{-# INLINE singleChain #-}
-- | Constructs a chain with only one check.
singleChain :: Check e m a -> CheckChain e m a
singleChain :: Check e m a -> CheckChain e m a
singleChain x :: Check e m a
x = [Check e m a] -> CheckChain e m a
forall e (m :: * -> *) a. [Check e m a] -> CheckChain e m a
CheckChain [ Check e m a
x ]
    

-- | These are the functions used to validate data. Return either a validated result or a sequence of all validation errors that occured.
{-# INLINABLE validate' #-}
validate' :: Validatable e Identity a => Unvalidated a -> Either (Seq e) a
validate' :: Unvalidated a -> Either (Seq e) a
validate' u :: Unvalidated a
u@(Unvalidated x :: a
x) = 
    a -> CheckResult e -> Either (Seq e) a
forall a e. a -> CheckResult e -> Either (Seq e) a
checkResultToEither a
x 
    (CheckResult e -> Either (Seq e) a)
-> (Unvalidated a -> CheckResult e)
-> Unvalidated a
-> Either (Seq e) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity (CheckResult e) -> CheckResult e
forall a. Identity a -> a
runIdentity 
    (Identity (CheckResult e) -> CheckResult e)
-> (Unvalidated a -> Identity (CheckResult e))
-> Unvalidated a
-> CheckResult e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Check e Identity a -> Unvalidated a -> Identity (CheckResult e)
forall e (m :: * -> *) a.
Check e m a -> Unvalidated a -> m (CheckResult e)
runCheck Check e Identity a
forall e (m :: * -> *) a. Validatable e m a => Check e m a
defaultCheck 
    (Unvalidated a -> Either (Seq e) a)
-> Unvalidated a -> Either (Seq e) a
forall a b. (a -> b) -> a -> b
$ Unvalidated a
u

{-# INLINABLE validate #-}
validate :: (Validatable e m a, Functor m) => Unvalidated a -> m (Either (Seq e) a)
validate :: Unvalidated a -> m (Either (Seq e) a)
validate u :: Unvalidated a
u@(Unvalidated x :: a
x) = 
    (CheckResult e -> Either (Seq e) a)
-> m (CheckResult e) -> m (Either (Seq e) a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> CheckResult e -> Either (Seq e) a
forall a e. a -> CheckResult e -> Either (Seq e) a
checkResultToEither a
x)
    (m (CheckResult e) -> m (Either (Seq e) a))
-> (Unvalidated a -> m (CheckResult e))
-> Unvalidated a
-> m (Either (Seq e) a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Check e m a -> Unvalidated a -> m (CheckResult e)
forall e (m :: * -> *) a.
Check e m a -> Unvalidated a -> m (CheckResult e)
runCheck Check e m a
forall e (m :: * -> *) a. Validatable e m a => Check e m a
defaultCheck 
    (Unvalidated a -> m (Either (Seq e) a))
-> Unvalidated a -> m (Either (Seq e) a)
forall a b. (a -> b) -> a -> b
$ Unvalidated a
u



class Validatable (e :: Type) (m :: Type -> Type) (a :: Type) | a -> m, a -> e where

    checkChain :: CheckChain e m a
    default checkChain :: (Generic a, GValidatable e m (Rep a)) => CheckChain e m a
    checkChain = (a -> Rep a Any) -> CheckChain e m (Rep a Any) -> CheckChain e m a
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap a -> Rep a Any
forall a x. Generic a => a -> Rep a x
from CheckChain e m (Rep a Any)
forall k e (m :: * -> *) (rep :: k -> *) (x :: k).
GValidatable e m rep =>
CheckChain e m (rep x)
gCheckChain

    defaultCheck :: Check e m a
    default defaultCheck :: Applicative m => Check e m a
    defaultCheck = [Check e m a] -> Check e m a
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([Check e m a] -> Check e m a)
-> (CheckChain e m a -> [Check e m a])
-> CheckChain e m a
-> Check e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CheckChain e m a -> [Check e m a]
forall e (m :: * -> *) a. CheckChain e m a -> [Check e m a]
runCheckChain (CheckChain e m a -> Check e m a)
-> CheckChain e m a -> Check e m a
forall a b. (a -> b) -> a -> b
$ CheckChain e m a
forall e (m :: * -> *) a. Validatable e m a => CheckChain e m a
checkChain

    isValid ::  Unvalidated a -> m Bool
    default isValid :: Applicative m => Unvalidated a -> m Bool
    isValid u :: Unvalidated a
u = ([CheckResult e] -> Bool) -> m [CheckResult e] -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((CheckResult e -> Bool) -> [CheckResult e] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CheckResult e -> Bool
forall e. CheckResult e -> Bool
passed) (m [CheckResult e] -> m Bool) -> m [CheckResult e] -> m Bool
forall a b. (a -> b) -> a -> b
$ (Check e m a -> m (CheckResult e))
-> [Check e m a] -> m [CheckResult e]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (((Unvalidated a -> m (CheckResult e))
-> Unvalidated a -> m (CheckResult e)
forall a b. (a -> b) -> a -> b
$ Unvalidated a
u) ((Unvalidated a -> m (CheckResult e)) -> m (CheckResult e))
-> (Check e m a -> Unvalidated a -> m (CheckResult e))
-> Check e m a
-> m (CheckResult e)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Check e m a -> Unvalidated a -> m (CheckResult e)
forall e (m :: * -> *) a.
Check e m a -> Unvalidated a -> m (CheckResult e)
runCheck) ([Check e m a] -> m [CheckResult e])
-> [Check e m a] -> m [CheckResult e]
forall a b. (a -> b) -> a -> b
$ CheckChain e m a -> [Check e m a]
forall e (m :: * -> *) a. CheckChain e m a -> [Check e m a]
runCheckChain CheckChain e m a
forall e (m :: * -> *) a. Validatable e m a => CheckChain e m a
checkChain
    



deriving via TrivialCheck ()         instance Validatable Void Identity ()
deriving via TrivialCheck Bool       instance Validatable Void Identity Bool 
deriving via TrivialCheck Char       instance Validatable Void Identity Char 
deriving via TrivialCheck Double     instance Validatable Void Identity Double 
deriving via TrivialCheck Float      instance Validatable Void Identity Float 
deriving via TrivialCheck Int        instance Validatable Void Identity Int 
deriving via TrivialCheck Int8       instance Validatable Void Identity Int8 
deriving via TrivialCheck Int16      instance Validatable Void Identity Int16 
deriving via TrivialCheck Int32      instance Validatable Void Identity Int32
deriving via TrivialCheck Int64      instance Validatable Void Identity Int64
deriving via TrivialCheck Integer    instance Validatable Void Identity Integer
 
instance (Validatable e m a, Applicative m) => (Validatable e m (Maybe a)) where
    checkChain :: CheckChain e m (Maybe a)
checkChain = Check e m a -> Check e m (Maybe a)
forall (t :: * -> *) (m :: * -> *) e a.
(Traversable t, Applicative m) =>
Check e m a -> Check e m (t a)
traverseWithCheck (Check e m a -> Check e m (Maybe a))
-> CheckChain e m a -> CheckChain e m (Maybe a)
forall e (m :: * -> *) a e' (n :: * -> *) b.
(Check e m a -> Check e' n b)
-> CheckChain e m a -> CheckChain e' n b
`overChain` CheckChain e m a
forall e (m :: * -> *) a. Validatable e m a => CheckChain e m a
checkChain

instance (Validatable e m b, Validatable e m a, Applicative m) => Validatable e m (Either a b) where
    checkChain :: CheckChain e m (Either a b)
checkChain = Check e m b -> Check e m (Either a b)
forall (t :: * -> *) (m :: * -> *) e a.
(Traversable t, Applicative m) =>
Check e m a -> Check e m (t a)
traverseWithCheck (Check e m b -> Check e m (Either a b))
-> CheckChain e m b -> CheckChain e m (Either a b)
forall e (m :: * -> *) a e' (n :: * -> *) b.
(Check e m a -> Check e' n b)
-> CheckChain e m a -> CheckChain e' n b
`overChain` CheckChain e m b
forall e (m :: * -> *) a. Validatable e m a => CheckChain e m a
checkChain

instance (Validatable e m a, Applicative m) => (Validatable e m [a]) where
    checkChain :: CheckChain e m [a]
checkChain = Check e m a -> Check e m [a]
forall (t :: * -> *) (m :: * -> *) e a.
(Traversable t, Applicative m) =>
Check e m a -> Check e m (t a)
traverseWithCheck (Check e m a -> Check e m [a])
-> CheckChain e m a -> CheckChain e m [a]
forall e (m :: * -> *) a e' (n :: * -> *) b.
(Check e m a -> Check e' n b)
-> CheckChain e m a -> CheckChain e' n b
`overChain` CheckChain e m a
forall e (m :: * -> *) a. Validatable e m a => CheckChain e m a
checkChain


------------------------------------------------------------------------------------------------------
-- $derivHelper
-- == Helper for deriving Validatable
-- Intended for use with `-XDerivingVia` like
-- 
-- > data X = X Int
-- >     deriving (Validatable Void Identity) via (TrivialCheck X)
-- > -- or with `-XStandaloneDeriving`
-- > data Y = Y String
-- > deriving via (TrivialCheck Y) instance (Validatable Void Identity Y) 


newtype TrivialCheck a = TrivialCheck { TrivialCheck a -> a
unTrivialCheck :: a }

instance Validatable Void Identity (TrivialCheck a) where
    {-# INLINE checkChain #-}
    checkChain :: CheckChain Void Identity (TrivialCheck a)
checkChain = CheckChain Void Identity (TrivialCheck a)
forall e (m :: * -> *) a. CheckChain e m a
emptyChain
    {-# INLINE defaultCheck #-}
    defaultCheck :: Check Void Identity (TrivialCheck a)
defaultCheck = Check Void Identity (TrivialCheck a)
forall a. Monoid a => a
mempty
    {-# INLINE isValid #-}
    isValid :: Unvalidated (TrivialCheck a) -> Identity Bool
isValid = Identity Bool -> Unvalidated (TrivialCheck a) -> Identity Bool
forall a b. a -> b -> a
const (Bool -> Identity Bool
forall a. a -> Identity a
Identity Bool
True)





------------------------------------------------------------------------------------------------------
-- The generic instance

class GValidatable (e :: Type) (m :: Type -> Type) (rep :: k -> Type) | rep -> m, rep -> e where
    gCheckChain :: CheckChain e m (rep x)

instance GValidatable Void Identity V1 where
    gCheckChain :: CheckChain Void Identity (V1 x)
gCheckChain = CheckChain Void Identity (V1 x)
forall a. Monoid a => a
mempty

instance GValidatable Void Identity U1 where
    gCheckChain :: CheckChain Void Identity (U1 x)
gCheckChain = CheckChain Void Identity (U1 x)
forall a. Monoid a => a
mempty

instance Validatable e m a => GValidatable e m  (K1 i a) where
    gCheckChain :: CheckChain e m (K1 i a x)
    gCheckChain :: CheckChain e m (K1 i a x)
gCheckChain = (K1 i a x -> a) -> CheckChain e m a -> CheckChain e m (K1 i a x)
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap K1 i a x -> a
forall i c k (p :: k). K1 i c p -> c
unK1 CheckChain e m a
forall e (m :: * -> *) a. Validatable e m a => CheckChain e m a
checkChain

instance (Applicative m, GValidatable e m f, GValidatable e m g) => GValidatable e m (f :*: g) where
    gCheckChain :: CheckChain e m ((:*:) f g x)
gCheckChain = ((:*:) f g x -> (f x, g x))
-> CheckChain e m (f x)
-> CheckChain e m (g x)
-> CheckChain e m ((:*:) f g x)
forall (f :: * -> *) a b c.
Divisible f =>
(a -> (b, c)) -> f b -> f c -> f a
divide (:*:) f g x -> (f x, g x)
forall k (f :: k -> *) (g :: k -> *) (p :: k).
(:*:) f g p -> (f p, g p)
id_tup CheckChain e m (f x)
forall k e (m :: * -> *) (rep :: k -> *) (x :: k).
GValidatable e m rep =>
CheckChain e m (rep x)
gCheckChain CheckChain e m (g x)
forall k e (m :: * -> *) (rep :: k -> *) (x :: k).
GValidatable e m rep =>
CheckChain e m (rep x)
gCheckChain
        where id_tup :: (:*:) f g p -> (f p, g p)
id_tup (x :: f p
x :*: y :: g p
y) = (f p
x, g p
y)

instance (GValidatable e m f, GValidatable e m g, Applicative m) => GValidatable e m (f :+: g) where
    gCheckChain :: CheckChain e m ((:+:) f g x)
gCheckChain = ((:+:) f g x -> Either (f x) (g x))
-> CheckChain e m (f x)
-> CheckChain e m (g x)
-> CheckChain e m ((:+:) f g x)
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose (:+:) f g x -> Either (f x) (g x)
forall k (f :: k -> *) (g :: k -> *) (p :: k).
(:+:) f g p -> Either (f p) (g p)
id_sum CheckChain e m (f x)
forall k e (m :: * -> *) (rep :: k -> *) (x :: k).
GValidatable e m rep =>
CheckChain e m (rep x)
gCheckChain CheckChain e m (g x)
forall k e (m :: * -> *) (rep :: k -> *) (x :: k).
GValidatable e m rep =>
CheckChain e m (rep x)
gCheckChain
        where id_sum :: (:+:) f g p -> Either (f p) (g p)
id_sum = \case
                L1 l :: f p
l -> f p -> Either (f p) (g p)
forall a b. a -> Either a b
Left f p
l
                R1 r :: g p
r -> g p -> Either (f p) (g p)
forall a b. b -> Either a b
Right g p
r

instance (GValidatable e m rep) => GValidatable e m (M1 i c rep) where
    gCheckChain :: CheckChain e m (M1 i c rep x)
gCheckChain = (M1 i c rep x -> rep x)
-> CheckChain e m (rep x) -> CheckChain e m (M1 i c rep x)
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap M1 i c rep x -> rep x
forall i (c :: Meta) k (f :: k -> *) (p :: k). M1 i c f p -> f p
unM1 CheckChain e m (rep x)
forall k e (m :: * -> *) (rep :: k -> *) (x :: k).
GValidatable e m rep =>
CheckChain e m (rep x)
gCheckChain